【C++ Primer 第15章】定义派生类拷贝构造函数、赋值运算符

学习资料

派生类的赋值运算符/赋值构造函数也必须处理它的基类成员的赋值html

• C++ 基类构造函数带参数的继承方式及派生类的初始化ios

 

定义拷贝构造函数

【注意】对派生类进行拷贝构造时,若是想让基类的成员也同时拷贝,就必定要在派生类拷贝构造函数初始化列表中显示调用基类拷贝构造函数(固然在函数体内将基类部分的值拷贝也是能够的,只不过它是先用默认构造函数初始化后再修改的基类成员变量的值,效率比较低),不然它会调用基类的默认构造函数,而不会对基类的成员变量拷贝值,这样生成的对象,它的派生类部分和被拷贝的对象派生类部分同样,而基类部分则是默认构造函数的初始化结果。app

代码例子1:函数

 1 #include <iostream>
 2 using namespace std;  3 
 4 class A  5 {  6 public:  7     A() { cout << "A default constructor" << endl; }  8     A(A&) { cout << "A copy constructor" << endl; }  9 }; 10 class B : public A 11 { 12 public: 13     B() { cout << "A default constructor" << endl; } 14     B(B &b) { cout << "B copy constructor" << endl; } 15 }; 16 
17 int main() 18 { 19  B b; 20     B c = b; 21     return 0; 22 }

输出结果:学习

 

 

代码例子2:this

 1 #include <iostream>
 2 using namespace std;  3 
 4 class A  5 {  6 public:  7     A() { cout << "A default constructor" << endl; }  8     A(A&) { cout << "A copy constructor" << endl; }  9 }; 10 class B : public A 11 { 12 public: 13     B() { cout << "A default constructor" << endl; } 14     B(B &b) : A(b) { cout << "B copy constructor" << endl; } 15 }; 16 
17 int main() 18 { 19  B b; 20     B c = b; 21     return 0; 22 }

输出结果:spa

 

 

C++ 基类构造函数带参数的继承方式及派生类的初始化.net

在定义类的时候,会遇到基类的构造函数带参数,而子类子类构造函数不带参数,这时候若是以代码 a 的方式创建派生类则会出错。code

 1 class A  2 {  3     public:  4         A(int x, int y): i(x), j(y) {}  5     private:  6         int i, j;  7 };  8 
 9 class B : public A 10 { 11     public: 12         B() { cout << "init B" << endl; } 13 };

在创建B类对象时,编译出错: 
 C:\Documents and Settings\admin\桌面\Text1.cpp(104) : error C2512: ‘A’ : no appropriate default constructor available htm

 

解决这个问题应该在A的构造函数中显式调用基类的带参构造函数。由于在基类中定义了带参构造函数,编译器不会提供默认构造函数。(或者能够在基类中增长一个不带参数的构造函数)这个问题将解决。 
代码 b 采用的是调用基类带参构造函数的方式:

代码 b:

 1 class A  2 {  3     public:  4         A(int x, int y): i(x), j(y) {}  5     private:  6         int i, j;  7 };  8 
 9 class B : public A 10 { 11     public: 12         B() A(10,20) { cout << "init B" << endl; } 13 };

 

经过在基类中增长一个不带参数的构造函数: 
代码 c:

 1 class A  2 {  3     public:  4         A(int x, int y): i(x), j(y) {}  5         A();   //不带参数的构造函数
 6     private:  7         int i, j;  8 };  9 
10 class B:public A 11 { 12     public: 13         B(): A(10,20) { cout << "init B" << endl; } 14 };

 

定义派生类赋值运算符

与拷贝和移动构造函数同样,派生类的赋值运算符也必须为其基类部分赋值。

1 // Base::operator=(const Base&) 不会被自动调用
2 D& D::operator=(const D &rhs) 3 { 4     Base::operator=(rhs);  //为基类部分赋值 5     //按照过去的方式为派生类的成员赋值
6     return *this; 7 }

 举例说明:

 1 class base 
 2 {  3 public:  4   base(int initialvalue = 0): x(initialvalue) {}  5 
 6 private:  7   int x;  8 };  9 
10 class derived : public base 
11 { 12 public: 13   derived(int initialvalue): base(initialvalue), y(initialvalue) {} 14   derived& operator=(const derived& rhs); 15 
16 private: 17   int y; 18 }; 19 
20 逻辑上说,derived的赋值运算符应该象这样: 21 derived& derived::operator = (const derived& rhs) // 错误的赋值运算符
22 {                                                 // 请注意d1的base部分没有被赋值操做改变。
23   if (this == &rhs) 24     return *this; 25   y = rhs.y; 26   return *this; 27 } 28 
29 不幸的是,它是错误的,由于derived对象的base部分的数据成员x在赋值运算符中未受影响。例如,考虑下面的代码段: 30 
31 void assignmenttester() 32 { 33   derived d1(0);      // d1.x = 0, d1.y = 0
34   derived d2(1);      // d2.x = 1, d2.y = 1
35 
36   d1 = d2;            // d1.x = 0, d1.y = 1
37 } 38 
39 
40 derived& derived::operator = (const derived& rhs) // 正确的赋值运算符
41 { 42   if (this == &rhs) 43     return *this; 44 
45   base::operator = (rhs);    // 调用this->base::operator=
46   y = rhs.y; 47 
48   return *this; 49 }
相关文章
相关标签/搜索