3.7 C++派生类构造函数调用规则

参考:http://www.weixueyuan.net/view/6364.html

总结:

  派生类构造函数可以自动调用基类的默认构造函数而无需显式调用。

  生类构造函数可以自动调用基类的默认构造函数,但是前提是默认构造函数必须存在。

  当基类没有默认构造函数时,派生类则无法自动调用基类的默认构造函数了。遇到这种情况有两种解决方案:其一,在基类中定义一个默认构造函数(不带参数的构造函数),例如上一节中的例2;其二,派生类中的每一个构造函数都显式的调用基类中的带参构造函数。

  建议在设计类的时候为每一个类设计一个默认构造函数,毕竟默认构造函数并不会妨碍构造函数的显式调用。

  在创建派生类对象时,必须显式或隐式地调用基类的某一个构造函数 

派生类构造函数可以自动调用基类的默认构造函数而无需显式调用。例如在上一节例2中,我们如果将condingbook类中的默认构造函数codingbook():book(){lang = none;}语句修改为codingbook(){lang = none;},则这个程序运行结果依然保持不变,因为派生类的构造函数会自动调用基类的默认构造函数。

生类构造函数可以自动调用基类的默认构造函数,但是前提是默认构造函数必须存在。通常情况下,默认构造函数系统会自动生成的,但是如果在基类中,我们自己定义了一个带参数的构造函数,这个时候,系统是不会为基类自动生成默认构造函数的,这个时候派生类则无法自动调用基类的默认构造函数了,因为基类根本就不存在默认构造函数。遇到这种情况有两种解决方案:其一,在基类中定义一个默认构造函数(不带参数的构造函数),例如上一节中的例2;其二,派生类中的每一个构造函数都显式的调用基类中的带参构造函数。

例1:

class base
{
public:
    base(int a){x = a; y = 0;}
    base(int a, int b){x = a; y = b;}
private:
    int x;
    int y;
};

class derived: public base
{
public:
    derived(){z = 0;}
    derived(int c){z = c;}
private:
    int z;
};

我们来看一下这个例子,这个例子里面先定义了一个类base作为基类,基类中拥有两个成员变量x和y,同时定义了两个带参数的构造函数,两个都是带参构造函数,如此一来类base就不会自动生成默认构造函数了。再来看派生类定义,派生类中新增了成员变量z,并且定义了一个带参构造函数和一个默认构造函数。但是如此定义,编译器会提示语法错误,因为派生类的构造函数没有显示调用基类构造函数。解决这个问题的方法在上面说了,一个是在基类自己定义一个默认构造函数,另外一种方法是显示调用基类构造函数。当然在设计类的时候推荐使用后者,毕竟构造函数就是为了初始化成员变量的,如果不显式调用基类构造函数,则从基类中继承过来的成员变量将得不到初始化,这一般来说都不是我们所希望看到的。

同时,我们还建议在设计类的时候为每一个类设计一个默认构造函数,毕竟默认构造函数并不会妨碍构造函数的显式调用。通常我们还会遇到这样一种情况,派生类中并未显式定义构造函数,这个时候派生类中只有系统自动生成的默认构造函数,如此一来,如果我们不为基类设计一个默认构造函数,则程序就会编译出错。这种错误很玄妙,如果不小心还真是难以发现。为了避免这种情况的发生,我们建议为每一个类设计一个默认构造函数。

根据以上两点建议,我们将例1进行修改,正确代码如下。

例2:

#include<iostream>
using namespace std;

class base
{
public:
    base(){x = 0; y = 0;}
    base(int a){x = a; y = 0;}
    base(int a, int b){x = a; y = b;}
private:
    int x;
    int y;
};

class derived: public base
{
public:
    derived():base(){z = 0;}
    derived(int a, int b, int c):base(a,b){z = c;}
private:
    int z;
};

int main()
{
    derived A;
    derived B(1,2,3);
    return 0;
}

在这个例子中,我们将例1中出现的问题采用双管齐下的方式解决了,为基类定义了默认构造函数,并且在派生类中显式地调用基类中的构造函数。

总的来说,在创建派生类对象时,必须显式或隐式地调用基类的某一个构造函数,这一点非常重要。当然被调用的基类的构造函数可以是带参构造函数,也可以是默认构造函数。

原文地址:https://www.cnblogs.com/yongpan/p/7631837.html