CPP 11. 使用类 2020-11-09 浏览量 712 暂无评论 # 第11章 使用类 ## 11.1 运算符重载 运算符重载是一种形式的C++多态,可使代码看起来更自然,隐藏内部机理,强调实质。 ```cpp operatorop(argument-list) // 重载+运算符 operator+() ``` 🌈一些限制: 1. 重载后的运算符必须至少有一个操作数是用户定义的类型,防止用户为标准类型重载运算符; 2. 使用运算符时不能违反操作符原来的句法规则,包括优先级; 3. **不能创建新运算符**; 4. 不能重载下面的运算符: - sizeof - . - .* - :: - ?: - typeid - 强制类型转换运算符const_cast, dynamic_cast, reinterpret_cast, static_cast 5. 下面的运算符只能使用成员函数重载 - = - () - [] - -> ## 11.2 友元 🐸小知识: 1. 友元有三种:友元函数、友元类、友元成员函数。 2. **通过让函数成员友元函数,可以赋予该函数与类的成员函数相同的访问权限。** 在为类重载二元运算符时(操作数类型不一样)常常需要友元,以实现交换顺序也能运算,而不是必须左侧操作数为调用对象。 3. **注意友元函数不在类作用域内,因此使用类成员时要加限定。** **创建友元函数:把原型放在类声明中,并在前面加上关键字friend,但定义时不需要加friend,也不需要加限定符** ```cpp Time operator*(double n) const; A = B * 2.75; 将被转换为下面的成员函数调用 A = B.operator*(2.75); 那A = 2.75 * B怎么办呢?这时候友元函数就派上用场了 friend Time operator*(double m, const Time & t); 意味着以下两点: 1. 它不是成员函数; 2. 它与成员函数的访问权限相同。 下面的两个原型将冲突 Time operator+(const Time & t) const; friend Time operator+(const Time & t1, const Time & t2); ``` **运算符<<重载** ```cpp 1. 第一种 void operator<<(ostream & os, const Time & t) { os << t.hours << " hours, " << t.minutes << " minutes"; } 2. 第二种 ostream & operator<<(ostream & os, const Time & t) { os << t.hours << " hours, " << t.minutes << " minutes"; return os; } 第一种重载不可以使用`cout << "Trip time: " << trip << " (Tuesday)\n";` 第二种重载就可以,因为它返回的是ostream对象的引用。 ``` ## 11.3 类的自动转换和强制类型转换 🐸小知识: 1. 只有接受一个参数的构造函数才能作为转换函数,如果是多个参数,但第二个以后都提供默认值也可以; 2. 只有接受一个参数的构造函数可以将类型与该参数相同的值转换为类; 3. 构造函数只用于从某种类型到类类型的转换,要进行相反的转换,需要使用**转换函数**; 4. 默认的复制构造函数和赋值运算符为浅复制,即对成员进行逐个复制,可能导致数据受损; 5. delete[]与使用new[]初始化的指针和空指针`str = 0; str = nullptr;`兼容 **构造函数类型转换** ```cpp Stonewt(double lbs); Stonewt myCat; myCat = 19.6; // 如果声明了要显式,则该语句无效 mycat = Stonewt(19.6); mycat = (Stonewt) 19.6; 程序将使用构造函数Stonewt(double)来创建一个临时的Stonewt对象,并将19.6作为初始化值,随后,采用逐成员赋值方式将该临时对象的内容复制到mtCar中,这一过程叫隐式转换。 可以使用explicit关闭自动隐式转换。(谨慎地使用隐式转换) explicit Stonewt(double lbs); ``` **转换函数类型转换** ```cpp 声明 operator typeName() const; 定义 className::operator typeName() const { return typeName (xxx) } ``` **复制构造函数** 用于将一个对象复制到新创建的对象中。 **每当程序生成了对象副本时,编译器都将使用复制构造函数。** ```cpp 原型 Class_name(const Class_name &); 何时调用? 新建一个对象并将其初始化为同类现有对象时,复制构造函数将被调用 假设motto是一个StringBad对象,则下面4种声明都将调用复制构造函数: StringBad ditto(motto); StringBad metto = motto; StringBad also = StringBad(motto); StringBad * pStringBad = new StringBad(motto); ``` **赋值运算符** 将已有的对象赋给另一个对象时,将使用重载的赋值运算符。 ```cpp StringBad headline1("Jineng Han"); StringBad knot; knot = headline1; ``` 赞赏 微信支付 支付宝支付