第十一章 使用类
下面的程序涉及到了类的构造函数,默认构造函数,析构函数,转换函数,友元函数,运算符重载。
1 //头文件,a.h 2 #ifndef a_H_//宏名不应以数字打头 3 #define a_H_ 4 5 #include<string> 6 7 class Animal 8 { 9 private: 10 std::string animal; 11 int weight; 12 int num; 13 14 public: 15 Animal(); 16 explicit Animal(std::string &, int n = 1, int w = 30); 17 ~Animal(); 18 //运算符重载 19 Animal operator+(Animal &aml) const; 20 //友元 21 friend Animal & operator+(Animal &aml, int); 22 //转换函数(C++98中explicit不能用于转换函数,只能用于构造函数) 23 operator std::string() const; 24 25 void show(); 26 27 }; 28 #endif
1 //类定义 2 #include "a.h" 3 #include<string> 4 #include<iostream> 5 6 Animal::Animal() 7 { 8 animal = "none"; 9 num = weight = 0; 10 } 11 12 Animal::Animal(std::string &aml, int n, int w) 13 { 14 animal = aml; 15 num = n; 16 weight = w; 17 } 18 19 Animal::~Animal() 20 { 21 std::cout << animal << "->" << num << "->" << weight << "->" << "byb!!" << std::endl; 22 } 23 24 Animal Animal::operator+(Animal &aml) const 25 { 26 return Animal(aml.animal, aml.num+num, aml.weight+weight); 27 } 28 29 30 Animal::operator std::string() const 31 { 32 return animal; 33 } 34 35 void Animal::show() 36 { 37 std::cout << animal << std::endl << num << std::endl << weight << std::endl; 38 } 39 40 //友元 41 Animal & operator+(Animal &aml, int n) 42 { 43 aml.num += n; 44 return aml; 45 }
1 #include<iostream> 2 #include "a.h" 3 4 int main() 5 { 6 { 7 std::string aml= "tiger"; 8 Animal Tiger0(aml, 30, 1); 9 Animal Tiger1(aml, 40, 1); 10 Animal Tiger2(aml, 10, 3); 11 Animal tol_Tiger = Tiger0+Tiger1+Tiger2;//调用重载的运算符‘+’ 12 tol_Tiger.show(); 13 } 14 { 15 std::string aml1= "sheep"; 16 // Animal Sheep = aml1;//单参数构造函数,隐式类型转换(用关键字explicit限定构造函数,将禁止这种隐式转换) 17 // Sheep.show(); 18 19 Animal Sheep2(aml1);//显示的调用单参数构造函数 20 std::string aml2 = Sheep2;//调用转换函数 21 std::cout << aml2 << std::endl; 22 } 23 24 { 25 Animal What;//隐式地调用默认构造函数 26 Animal W2 = What +2;//使用友元 27 What.show(); 28 } 29 30 system("pause"); 31 return 0; 32 }
C++提供了另一种访问权限——友元。
友元有3种:友元函数;友元类;友元成员函数。
本章只涉及到友元函数。
在为类重载二元运算符时常常需要友元。
创建友元
将其原型放在类声明中,并在原型声明前加上关键字friend。
其与成员函数的访问权限相同。
类方法和友元是表达类接口的两种不同机制。
类的自动转换和强制类型转换
在C++中,接受一个参数的构造函数为 将类型与该参数相同的值转换成类 提供了蓝图。
即,可以将与构造函数参数类型相同的变量转换为该类对象(隐式转换),C++新增了关键字explicit用于关闭该特性,但仍然允许显式转换。
转换函数
构造函数只用于从某种类型到类类型的转换。要进行相反的转换,必须使用特殊的C++运算符——转换函数。
转换函数是用户定义的强制类型转换,可以像使用强制类型转换那样使用它们。
创建转换函数
operator typename();
转换函数必须是类方法;不能指定返回类型;不能有参数。
当类定义了两种或更多的转换时,可以使用显式强制类型转换指出要使用哪个转换函数。
原则上,最好使用显式转换,而避免隐式转换。
在C++98中,关键字explicit不能用于转换函数,但C++11消除了这个限制,在C++11中可将转换运算符声明为显式的。
使用转换函数时的一个问题
设Stock是一个类,其中定义了单参数构造函数Stock(long),并且没有使用关键字explicit限定;而且定义了转换函数operate long();重载了运算符“+”,操作数为Stock类对象。
代码如下:
1 Stock st1(1000); 2 long st2 = 200; 3 Sotck ST; 4 ST = st1 + st2;
那么第四行是先将st1通过转换函数隐式转换为long整型再对long整型进行"+"操作,之后再转换到Stock类对象;还是先将st2通过构造函数隐式转换为Stock类对象再对Stock类对象进行"+"操作?
为避免以上问题在C++98中,最好用explicit限定构造函数禁止隐式转换。