运算符重载

运算符重载函数的形式是:
• 返回类型 operator 运算符符号 (参数说明) { //函数体的内部实现 }
• 至少有一个参数是自定义类型(数组,类)
• 如果是单目运算符,只传一个参数
• 如果是双目运算符,传两个参数
c++也规定了一些运算符不能够自定义重载 • 例如 ::、sizeof、.、?:
 
常见运算符重载函数的使用
• 一种是作为类的友元函数进行使用
如:friend void operator +(Test&,Test&);
作为类的友元函数
• 一种则是作为类的成员函数进行使用
如:Temp operator +(Temp &t){ ;}
 
MyStr& operator =(const MyStr& str)//赋值运算符
    {
        cout << "operator =" << endl;
        if (this != &str)
        {
            if (name != NULL)
                delete name;
            this->id = str.id;
            int len = strlen(str.name);
            name = new char[len + 1];
            strcpy_s(name, strlen(str.name) + 1, str.name);
        }
        return *this;
    }
Ⅱ.参数
一般地,赋值运算符重载函数的参数是函数所在类的const类型的引用(如上面例1),加const是因为:
①我们不希望在这个函数中对用来进行赋值的“原版”做任何修改。
②加上const,对于const的和非const的实参,函数就能接受;如果不加,就只能接受非const的实参。
用引用是因为:
这样可以避免在函数调用时对实参的一次拷贝,提高了效率。
注意:
上面的规定都不是强制的,可以不加const,也可以没有引用,甚至参数可以不是函数所在的对象,正如后面例2中的那样。
Ⅲ.返回值
一般地,返回值是被赋值者的引用,即*this(如上面例1),原因是
①这样在函数返回时避免一次拷贝,提高了效率。
②更重要的,这样可以实现连续赋值,即类似a=b=c这样。如果不是返回引用而是返回值类型,那么,执行a=b时,调用赋值运算符重载函数,在函数返回时,由于返回的是值类型,所以要对return后边的“东西”进行一次拷贝,得到一个未命名的副本(有些资料上称之为“匿名对象”),然后将这个副本返回,而这个副本是右值,所以,执行a=b后,得到的是一个右值,再执行=c就会出错。
 
为什么C++赋值运算符重载函数不能被继承?
#include<iostream>
#include<string.h>
using namespace std;
class A1 {
public:
    int operator =(int a) {
        return 8;
    }
 
    int operator +(int a) {
        return 9;
    }
};
class B1:public A1 {
public:
    int operator -(int a) {
        return 7;
    }
};
 
int main(int argc, char *argv[])
{
    B1 v;
    cout<< v + 2 <<endl; //OK, print 9
    cout<< v - 2 <<endl; //OK, print 7
    cout<< v = 2 <<endl; //Error, see below  test.cpp:29: error: no match for ‘operator<<’ in ‘std::cout << v’
    return 0;
}
意思是说编译器找不到int operator=(int a)这个成员函数可以调用。
真是怪了?明明int operator=(int a)这个函数是我从基类公有继承下来的函数,怎么编译器识别不了呢?遇到这种问题,第一反应就是查找MSDN以求得解释,微软告诉我:
“All overloaded operators except assignment (operator=) are inherited by derived classes.”
意思是说:除了赋值运算符重载函数以外,所有的运算符重载函数都可以被派生类继承。
我这个函数int operator=(int a)很不幸就是微软所说的“赋值运算符重载函数”,当然不能被继承!
 
1,每一个类对象实例在创建的时候,如果用户没有定义“赋值运算符重载函数”,那么,编译器会自动生成一个隐含和默认的“赋值运算符重载函数”。所以,B1的实际上的声明应该类似于下面这种情况:
class B1 : public A1  
{  
public:  
        B1& operator =(const B1& robj); // 注意这一行是编译器添加的  
        int operator-(int a)  
        {  
                return 7;  
        }  
};
 
2,C++标准规定:如果派生类中声明的成员与基类的成员同名,那么,基类的成员会被覆盖,哪怕基类的成员与派生类的成员的数据类型和参数个数都完全不同。显然,B1中的赋值运算符函数名operator =和基类A1中的operator =同名,所以,A1中的赋值运算符函数int operator=(int a);被B1中的隐含的赋值运算符函数B1& operator =(const B1& robj);所覆盖。 A1中的int operator=(int a);函数无法被B1对象访问。
 
3,程序中语句v = 2实际上相当于v.operator =(2);,但是A1中的int operator=(int a);已经被覆盖,无法访问。而B1中默认的B1& operator =(const B1& robj);函数又与参数2的整数类型不相符,无法调用。
4,为了确认B1中默认的B1& operator =(const B1& robj);函数的存在性,可以用以下代码验证:
B1 b;  
B1 v;   
v = b; // OK, 相当于调用v.operator =(b);  
 
5,所以,“赋值运算符重载函数”不是不能被派生类继承,而是被派生类的默认“赋值运算符重载函数”给隐藏了。
这就是C++赋值运算符重载函数不能被派生类继承的真实原因! 

转载于:https://www.cnblogs.com/gschain/p/11245057.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值