清华大学出版社《c++程序设计》(第三版)中简单总结的一些知识点
- C++不允许定义新的运算符,但允许运算符重载,重载运算符的函数名 operator加运算符
x=y+z 可以等价写为:x.operator=(y.operator+(z)) - 运算符重载有一系列限制,详情见P293
- 运算符重载函数至少有一个是参数是自定义类对象
- 重载为类的成员函数时,
§ 运算符通过类的对象调用,运算重载符可以通过this指针直接操作对象的数据成员(这个this指针就是类的对象传递给运算符函数的隐含参数)
§ 重载为类的成员函数时–>左操作数必须是成员函数所在类的一个对象(如果是单目,则指,则指其唯一的操作数) - 重载为友元函数时,
§ 运算符函数要操作的对象必须在参数列表中明确列出
§ 若左操作数是是其他类或者内部类型的对象–>则运算符必须作为非成员函数(一般是友元函数)重载(这里注意对比,操作符已经为某个类的成员函数,或者为了保留运算符可交换性等情况时,必须以友元函数的形式重载运算符)
- 重载为类的成员函数时,
单目运算符重载:
- 其操作数只能是自定义类的对象或者对象的引用
- 作为成员函数重载,唯一的操作数就是调用该函数的对象(参数是隐含参数this指针)
□ 声明时:bool String::operator ! ()
□ 定义时:例如bool String::operator ! ()
□ 调用时:函数调用 s1.operator !() ;表达式调用 !s1; - 作为友元函数重载时必须带一个参数,参数为自定义类对象或对象的引用
□ 声明时:friend bool String::operator ! (const String &S)
□ 定义时:例如bool String::operator ! (const String &S)
□ 调用时:函数调用 operator !(s1) ;表达式调用 !s1;
§ 可以看出,不管作为成员函数还是友元函数重载,使用表达式的方法调用时,都是一样的
- 作为成员函数重载,唯一的操作数就是调用该函数的对象(参数是隐含参数this指针)
- C++中特殊的单目运算符 自增++ 自减-- (以Complex的对象a为例)
- 作为前自增前自减时++a,参数列表和普通单目运算符一致
□ Complex operator++() 编译器将++a转成:a.operator++ ()
□ Complex operator++(Complex &) 编译器将++a转成:operator++ (a) - 作为后自增后自减时a–,参数列表带一个整形参数,是个伪参数,仅作为区分
□ Complex operator++(int) 编译器将a–转成:a.operator-- (0)
□ Complex operator++(Complex &,int) 编译器将a–转成:operator-- (a,0)
- 作为前自增前自减时++a,参数列表和普通单目运算符一致
双目运算符重载:
- 双目运算符可以被重载为带有一个参数的非静态成员函数(除了隐含参数之外,被操作数的对象)
String & String::operator += (const String &s) - 或者带有两个参数的非成员函数,(左操作数与被操作数对象,参是相同类的对象或对象的引用,如果类似前面<<和>>,就是不同类的对象或对象的引用)
String & String::operator += (const String &s,const String &x)
重载流插入和流提取运算符:
流插入<<为类ostream的一个成员函数,且为双目运算符,cout是类ostream的一个对象,如果想用cout输出自己定义的类型(以自定义类String为例) :
String s("asdsdd");
cout<< s <<endl;
需注意:
- 只能考虑以String类的友元函数的进行进行重载,(原因见p299)
- 且重载函数必须有两个参数:一个参数为类ostream的对象(cout)或对象引用,另一个参数为String的对象或对象引用,
- 且由于流插入运算符是可以连续调用的,所以函数的返回类型必须为ostream对象(cout)的引用
ostream & operator <<(ostream &output,const String &s) - 类似的,流提取>>为类istream的一个成员函数,左操作数为istream对象cin
istream & operator <<(istream &input, String &s)
赋值运算符:
其实赋值运算符不用重载就可以直接用在自定义类对象之间,其默认操作是逐个赋值对象的所有数据成员。这种方式对大多数类的对象是合适的(包括例13-1),但如果对象中包含动态分配的空间时,这种方法可能出错。
类型之间的转换:
当一个运算要涉及多种数据类型,需要将一种类型的数据转换成另外一种类型的数据,然后再进行该类型数据的运算。自定义类型----->另一种自定义类型、、自定义类型-------->内部类型
- 方式一:通过类型转换运算符函数将自定义类对象转换为其他类型对象
- 类型转换运算符必须是类的非静态成员函数,不能是友元函数,没有参数(内部函数,且为单目运算符),不能指定返回类型(因为返回的一定是要转换的类型),
- 函数原型为:operator Classname () const; 例如operator int () const; 若int obj是一个自定义对象 (int)obj; obj.operator int();
- 可以是显式的(int)s1,也可以是隐式的 string例中的s1+10
- 方式二:通过转换构造函数实现将其他类型对象转换成自定义类的对象
- ClassName(const OtherClass obj); ClassName为转换目标类的名字,OtherClass为被转换的其他类型的名字,唯一的参数就是其他类型的对象,转换构造函数将根据该对象初始化自定义类型的对象。