派生类构造函数

我们说基类的成员函数可以被继承,可以通过派生类的对象访问,但这仅仅指的是普通的成员函数,类的构造函数不能被继承。构造函数不能被继承是有道理的,因为即使继承了,它的名字和派生类的名字也不一样,不能成为派生类的构造函数,当然更不能成为普通的成员函数。

在设计派生类时,对继承过来的成员变量的初始化工作也要由派生类的构造函数完成,但是大部分基类都有 private 属性的成员变量,它们在派生类中无法访问,更不能使用派生类的构造函数来初始化。

这种矛盾在C++继承中是普遍存在的,解决这个问题的思路是:在派生类的构造函数中调用基类的构造函数。

以上摘自:http://c.biancheng.net/cpp/biancheng/view/231.html

  1 #include<iostream>
  2 using namespace std;
  3 class Computer
  4 {
  5 public:
  6     Computer() :price(0){
  7         cout << "基类默认构造函数被调用\n";
  8     }
  9     Computer(double my_price);
 10     ~Computer();
 11     virtual void display();
 12 
 13 protected:
 14     double price;
 15 };
 16 void Computer::display() {
 17     cout << "price:" << price << endl;
 18 }
 19 
 20 Computer::Computer(double my_price):price(my_price)
 21 {
 22     cout << "基类构造函数被调用\n";
 23 }
 24 
 25 Computer::~Computer()
 26 {
 27 }
 28 /* 派生类  DELL */
 29 class DELLComputer:public Computer
 30 {
 31 public:
 32     DELLComputer() :number(0) ,Computer(){
 33         cout << "DELL 默认构造函数被调用\n";
 34     }
 35     DELLComputer(double my_price, int my_number);
 36     virtual void display();
 37     ~DELLComputer();
 38 
 39 private:
 40     //double price;
 41     int number;
 42 
 43 };
 44 void DELLComputer::display() {
 45     cout << "price:" << price << "number:" << number << endl;
 46 }
 47 
 48 DELLComputer::DELLComputer(double my_price, int my_number):Computer(my_price),number(my_number)
 49 {
 50     cout << "DELL构造函数被调用:\n";
 51 }
 52 
 53 DELLComputer::~DELLComputer()
 54 {
 55 }
 56 /*派生类  HP                     */
 57 class HPComputer:public Computer
 58 {
 59 public:
 60     HPComputer():number(0),Computer() {
 61         cout << "HP 默认构造函数被调用:\n";
 62     }
 63     HPComputer(double my_price, int my_number);
 64     virtual void display();
 65     ~HPComputer();
 66 
 67 private:
 68     //double price;
 69     double number;
 70 };
 71 void HPComputer::display() {
 72     cout << "pirce:" << price << "number:" << number << endl;
 73 }
 74 HPComputer::HPComputer(double my_price, int my_number) :number(my_price),Computer(my_price)
 75 {
 76     cout << "HP 构造函数被调用:\n";
 77 }
 78 
 79 HPComputer::~HPComputer()
 80 {
 81 }
 82 
 83 int main() {
 84     Computer com1;
 85     com1.display();
 86     DELLComputer com2;
 87     com2.display();
 88     HPComputer com3;
 89     com3.display();
 90 
 91     Computer com11(25.0);
 92     com11.display();
 93     DELLComputer com21(23.0, 500);
 94     com21.display();
 95     HPComputer com31(24.0, 800);
 96     com31.display();
 97 
 98     Computer* ptr1 = &com21;  //基类指针可以指向派生类对象
 99     ptr1->display();
100     ptr1 = &com31;
101     ptr1->display();
102 
103     return 0;
104 }
 48 DELLComputer::DELLComputer(double my_price, int my_number):Computer(my_price),number(my_number)

74 HPComputer::HPComputer(double my_price, int my_number) :number(my_number),Computer(my_price)
  • 48,74行分别为俩个派生类的构造函数;
  • 标红部分为调用基类构造函数,不管先后顺序如何都是先调用基类的构造函数。
  •  

      构造函数的调用顺序

从上面的结果可以看出基类的构造函数总是被优先调用,说明创建派生类对象时,会先调用基类构造函数,再调用派生类构造函数,如果继承关系有好几层的话,例如:

A----->B----->C

那么创建C类对象时构造函数的执行顺序为:

A类构造函数---》B类构造函数---》C类构造函数

构造函数的调用顺序是按照继承的层次自顶向下、从基类再到派生类的。

还有一点要注意,派生类构造函数中只能调用直接基类的构造函数,不能调用间接基类的。以上面的 A、B、C 类为例,C 是最终的派生类,B 就是 C 的直接基类,A 就是 C 的间接基类。

C++ 这样规定是有道理的,因为我们在 C 中调用了 B 的构造函数,B 又调用了 A 的构造函数,相当于 C 间接地(或者说隐式地)调用了 A 的构造函数,如果再在 C 中显式地调用 A 的构造函数,那么 A 的构造函数就被调用了两次,相应地,初始化工作也做了两次,这不仅是多余的,还会浪费CPU时间以及内存,毫无益处,所以 C++ 禁止在 C 中显式地调用 A 的构造函数。 

摘自:http://c.biancheng.net/cpp/biancheng/view/231.html

基类构造函数的调用规则

事实上,通过派生类创建对象时必须要调用基类的构造函数,这是语法规定。换句话说,定义派生类构造函数时最好指明基类构造函数;如果不指明,就调用基类的默认构造函数(不带参数的构造函数);

将以上代码的第48行中的基类构造函数删去的话,即:

48 DELLComputer::DELLComputer(double my_price, int my_number):Computer(my_price),number(my_number)
48 DELLComputer::DELLComputer(double my_price, int my_number):number(my_number)

 

 

如果将基类 People 中不带参数的构造函数删除,那么会发生编译错误,因为创建对象 stu1 时需要调用 People 类的默认构造函数, 而 People 类中已经显式定义了构造函数,编译器不会再生成默认的构造函数。

另外,基类指针/引用可可以指向派生类对象。

 98     Computer* ptr1 = &com21;  //基类指针可以指向派生类对象
 99     ptr1->display();
100     ptr1 = &com31;
101     ptr1->display();

 

 

 

 

 

 

 

 

 

 

Computer(my_number)
posted @ 2020-06-18 14:30  每天都要吃早饭  阅读(398)  评论(0编辑  收藏  举报