C++重载

函数重载

函数重载:在同一个class内,可以声明几个功能类似的同名函数,但是这些同名函数的形式参数(指参数的个数、类型或者顺序)不同,样例如下:

#include <iostream>
#include <string>
using namespace std;

class PrintLog {
   public:
    void printLog(int value) {
        cout << "printLog(int value)" << endl;
    }

    void printLog(string str) {
        cout << "printLog(string str)" << endl;
    }

    void printLog(int value, string str) {
        cout << "printLog(int value, string str)" << endl;
    }
};

int main(int argc, char const* argv[]) {
    PrintLog pl;
    pl.printLog(1);
    pl.printLog("bengi");
    pl.printLog(1, "bengi");
    return 0;
}

输出如下:
printLog(int value)
printLog(string str)
printLog(int value, string str)


运算符重载

语法规则:operator后面接需要重载的符号,例如+运算符重载可以写为operator+

+ 算术运算符重载
需求:需要将两个class中的属性进行相加,将属性相加的结果赋值给新的class中的属性。可以使用全局函数进行重载,也可以用成员函数进行重载。

  1. 运用全局函数进行重载
#include <iostream>
#include <string>
using namespace std;

/* + 重载 */
class test {
   public:
    test() {}

    test(int value) {
        this->value = value;
    }

   public:
    int value;
};

/* 全局函数重载+的思维流程:
   1. 需求是t3 = t1 + t2; t3还是一个test类,所以返回值是test
   2. 需要执行的是t1 + t2,所以需要将t1和t2两个类作为参数传入
   3. 传入的参数不希望是重新拷贝出来的,保持一份数据,所以采用引用的方式传参
   4. 因为传入的是引用,所以为了避免被改动到,所以需要加const来修饰
 */
test operator+(const test& t1, const test& t2) {
    test t0;
    t0.value = t1.value + t2.value;
    return t0;
}

int main(int argc, char const* argv[]) {
    test t1(10);
    test t2(20);
    test t3;

    /* 需求:t3 = t1 + t2
       结果:t3.value = t1.value + t2.value; //10 + 20 = 30;
     */

    t3 = t1 + t2;
    cout << "t3.value: " << t3.value << endl; /* 输出:30 */
    return 0;
}
  1. 运用成员函数进行重载
#include <iostream>
#include <string>
using namespace std;

/* + 重载 */
class test {
   public:
    test() {}

    test(int value) {
        this->value = value;
    }

   public:
    int value;

   public:
    /* 成员函数重载+的思维流程:
       1. 需求是t3 = t1 + t2; t3还是一个test类,所以返回值是test
       2. t1 + t2 = t1.operator+(t2),因为this指针的指向是被调用成员函数的所属对象,所以参数传入t2即可
       3. 传入的参数不希望是重新拷贝出来的,保持一份数据,所以采用引用的方式传参
       4. 因为传入的是引用,所以为了避免被改动到,所以需要加const来修饰
     */
    test operator+(const test& t2) {
        cout << this->value << endl; /* 输出的是t1.value = 10 */
        test t0;
        t0.value = this->value + t2.value;
        return t0;
    }
};

int main(int argc, char const* argv[]) {
    test t1(10);
    test t2(20);
    test t3;

    /* 需求:t3 = t1 + t2
       结果:t3.value = t1.value + t2.value; //10 + 20 = 30;
     */

    t3 = t1 + t2;
    cout << "t3.value: " << t3.value << endl; /* 输出:30 */
    return 0;
}

<< 左移运算符重载

#include <iostream>
#include <string>
using namespace std;

/* << 重载 */
class test {
   public:
    test(int value) {
        this->value = value;
    }

   public:
    int value;
};

/* 全局函数重载<<的思维流程:
   1. 需求是cout << t1 << endl; 为了符合链式编程思想,有追加一个 << endl; 所以返回值需要定义为cout的类型ostream&(为何是引用,见3)
   2. 需要执行的是cout << t1,所以讲cout和t1作为参数传入
   3. 传入的参数不希望是重新拷贝出来的,保持一份数据,所以采用引用的方式传参。另外cout是标准输出流,也只能存在一份
   4. 因为传入的是引用,所以为了避免被改动到,所以需要加const来修饰
   5. 传入的参数cout前为何不加const,因为cout是标准输出流,本身没有加const修饰,如果硬加上会报错
 */

ostream& operator<<(ostream& cout, const test& t) {
    cout << t.value;
    return cout;
}

int main(int argc, char const* argv[]) {
    test t1(10);

    /* 需求:cout << t1 << endl;
       结果:输出 t1.value = 10;
     */

    cout << t1 << endl;
    return 0;
}

注意:<<运算符只能通过全局函数进行重载,原因如下:
如果我们通过成员函数进行重写,那么cout << t1实质上的代码等同于t1.operator<<(cout),将代码简写之后就变成了t1 << cout,这就不符合cout << t1的要求了,所以无法通过成员函数进行重写。

自增运算符重载
自增分成前置(++i)和后置(i++)

#include <iostream>
#include <string>
using namespace std;

/* i++和++i 重载 */
class test {
   public:
    test(int value) {
        this->value = value;
    }

    /* 成员函数重载++i的思维流程:
       1. 因为自增运算符是可以持续自增的,例如++(++i),所以返回值类型需要是原本的test class,即test&
       3. 因为++i是先加后用,所以不需要任何临时数据来转接,直接++this->value即可
    */
    test& operator++() {
        ++(this->value);
        return *this;
    }

    /* 成员函数重载i++的思维流程:
       1. 因为i++和++i都是使用的++,编译器为了区分两者,重载i++的时候,参数定义为operator++(int),加以区分
       2. 因为i++是先用后加,所以需要转接一下,才可以实现先用后加
       3. 因为i++是先用后加,用过之后再用就是++后的值了,所以不返回引用,直接返回值
     */
    test operator++(int) { /* int是一个占位参数,用来区分i++和++i */
        test temp = *this; /* 记录当前原本的值,然后让本身的值++,返回的是以前的值,从而实现先用后加的效果 */
        this->value++;
        return temp;
    }

   public:
    int value;
};

int main(int argc, char const* argv[]) {
    test t1(10);
    test t2(20);

    /* 需求1:++t1;
       结果:++t1.value;
     */
    ++(++t1);
    cout << t1.value << endl; /* 输出12 */

    /* 需求1:t1++;
       结果:t1.value++;
     */
    test t3 = t2++;
    cout << t2.value << endl; /* 输出21 */
    cout << t3.value << endl; /* 输出20  t3=t2++; 这个可以实现是因为编译器默认帮我们进行了值拷贝 */

    return 0;
}

= 赋值运算符重载

如果不实现=运算符重载,编译器会默认帮我们做值拷贝。

#include <iostream>
#include <string>
using namespace std;

class test {
   public:
    test(int a, int b) {
        this->a = a;
        this->b = b;
    }

   public:
    int a;
    int b;
};

/* 重载<<运算符 */
ostream& operator<<(ostream& cout, const test& t) {
    cout << t.a << " " << t.b;
    return cout;
}

int main(int argc, char const* argv[]) {
    test t1(1, 2);
    test t2 = t1; /* 不实现=运算符,编译器会默认帮我们做值拷贝 */

    cout << t1 << endl; /* 输出1 2 */
    cout << t2 << endl; /* 输出1 2 */
    return 0;
}

但是如果出现指针相关的,如果只进行值拷贝,会导致可能出现重复释放问题,所以需要重载,做到深拷贝,如下:

#include <iostream>
#include <string>
using namespace std;

class test {
   public:
    test(int a, int b, int c) {
        this->a = a;
        this->b = b;
        this->c = new int(c);
    }

    ~test() {
        if (this->c != NULL) {
            delete this->c;
            this->c = NULL;
        }
    }

    test& operator=(test& t) {
        cout << "opertor=" << endl;
        this->a = t.a;
        this->b = t.b;

        if (this->c != NULL) {
            delete this->c;
            this->c = NULL;
        }

        this->c = new int(*t.c);
        return *this;
    }

   public:
    int a;
    int b;
    int* c;
};

/* 重载<<运算符 */
ostream& operator<<(ostream& cout, const test& t) {
    cout << t.a << " " << t.b << " " << *t.c;
    return cout;
}

int main(int argc, char const* argv[]) {
    test t1(1, 2, 3);
    test t2(2, 3, 4);

    t2 = t1; /* 相当于执行 t2.operator=(t1) */
    cout << "t2 = t1" << endl;

    /* PS:如果用下面的方式,不会调用到重载的?? */
    test t3 = t1;

    cout << t1 << endl; /* 输出1 2 3*/
    cout << t2 << endl; /* 输出1 2 3*/
    cout << t3 << endl; /* 输出1 2 3*/
    return 0;
}

==/> 关系运算符重载

#include <iostream>
#include <string>
using namespace std;

class test {
   public:
    test(int a, int b) {
        this->a = a;
        this->b = b;
    }

    bool operator==(const test& t) {
        if (this->a == t.a && this->b == t.b) {
            return true;
        } else {
            return false;
        }
    }

    bool operator>(const test& t) {
        int t1 = this->a + this->b;
        int t2 = t.a + t.b;
        if (t1 > t2) {
            return true;
        } else {
            return false;
        }
    }

    int a;
    int b;
};

int main(int argc, const char** argv) {
    test t1(10, 10);
    test t2(10, 11);
    test t3(10, 10);

    /* 需求1:判断t1和t2是否相等,判断t1和t3是否相等。相等的条件是t1.a == t2.a && t1.b == t2.b
     */
    if (t1 == t2) {
        cout << "t1 == t2" << endl;
    } else {
        cout << "t1 != t2" << endl; /* 输出这句 */
    }

    if (t1 == t3) {
        cout << "t1 == t3" << endl; /* 输出这句 */
    } else {
        cout << "t1 != t3" << endl;
    }

    /* 需求2:判断t1和t2哪个更大,条件是t1.a+t1.b > t2.a+t2.b 则输出更大 */
    if (t1 > t2) {
        cout << "t1 > t2" << endl;
    } else {
        cout << "t1 <= t2" << endl; /* 输出这句 */
    }

    return 0;
}

() 函数调用运算符重载
重载()后因为非常类似函数,所以被称为仿函数

#include <iostream>
#include <string>
using namespace std;

class test {
   public:
    void operator()(int value) {
        cout << "print value: " << value << endl;
    }
};

int main(int argc, const char** argv) {
    test t;
    t(10); /* 输出:print value: 10 */

    test()(20); /* 匿名对象调用,输出:print value: 20 */
    
    return 0;
}

运算符重载+函数重载

#include <iostream>
#include <string>
using namespace std;

class test {
   public:
    test(int a, int b) {
        this->a = a;
        this->b = b;
    }

    /* 两个class之间相加 */
    test operator+(test& t) {
        test temp(0, 0);
        temp.a = this->a + t.a;
        temp.b = this->b + t.b;
        return temp;
    }

    test operator+(int value) {
        test temp(0, 0);
        temp.a = this->a + value;
        temp.b = this->b;
        return temp;
    }

    int a;
    int b;
};

/* 实现<<重载 */
ostream& operator<<(ostream& cout, const test& t) {
    cout << t.a << " " << t.b;
    return cout;
}

int main(int argc, const char** argv) {
    test t1(1, 2);
    test t2(1, 1);
    test t3 = t1 + t2; /* t1.operator+(t2) */
    test t4 = t1 + 10; /* t1.operator+(10) */

    cout << t1 << endl; /* 输出:1 2 */
    cout << t3 << endl; /* 输出:2 3 */
    cout << t4 << endl; /* 输出:11 2 */

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值