C++构造函数/析构函数继承

She*_*ohn 58 c++ inheritance constructor destructor

编辑:答案摘要

在下文中,B是A的子类.

这是一个术语问题; ctors和dtor 不是继承的,因为B的ctor/dtor 不会从A的界面借用.一个类至少有一个构造函数,并且只有一个析构函数.

  • 建设者:
    • B不从A继承构造函数;
    • 除非B的ctor明确地调用A的一个 ctor,否则A的默认ctor将 B的ctor主体之前自动调用(这个想法是A需要在B创建之前初始化).
  • 破坏者:
    • B不继承A的dtor;
    • 退出,B的析构函数会自动调用的析构函数.

致谢: 我特别感谢Oli Charlesworth和Kos的答案,我将Kos的答案作为解决方案,因为这是我最了解的答案.


原始邮政

当您在Google上搜索"C++析构函数继承站点:stackoverflow.com"时,您当前会发现以下帖子:

  1. 构造函数和析构函数继承:具有30k +声誉的两个用户说它是继承的,并且它不是
  2. 虚拟析构函数是继承的吗?:这里没有提到会指向析构函数不被继承的东西
  3. C++中的析构函数和继承?:评论似乎表明析构函数是继承的

Q1:我从实践中也知道的是,你不能使用与它的父构造函数相同的原型初始化派生对象而没有明确地定义派生类的构造函数,这是正确的吗?


尽管从帖子中可以清楚地看出析构函数似乎是继承的,但我仍然感到困惑的是,拥有32k声望的用户会说它不是.我写了一个小例子,应该澄清每个人的想法:

#include <cstdio>

/******************************/

// Base class
struct A
{
    A() { printf( "\tInstance counter = %d (ctor)\n", ++instance_counter ); }
    ~A() { printf( "\tInstance counter = %d (dtor)\n", --instance_counter ); }

    static int instance_counter;
};

// Inherited class with default ctor/dtor
class B : public A {};

// Inherited class with defined ctor/dtor
struct C : public A
{
    C() { printf("\tC says hi!\n"); }
    ~C() { printf("\tC says bye!\n"); }
};

/******************************/

// Initialize counter
int A::instance_counter = 0;

/******************************/

// A few tests
int main()
{
    printf("Create A\n"); A a;
    printf("Delete A\n"); a.~A();

    printf("Create B\n"); B b;
    printf("Delete B\n"); b.~B();

    printf("Create new B stored as A*\n"); A *a_ptr = new B();
    printf("Delete previous pointer\n"); delete a_ptr;

    printf("Create C\n"); C c;
    printf("Delete C\n"); c.~C();

}
Run Code Online (Sandbox Code Playgroud)

这是输出(用g ++ 4.4.3编译):

Create A
    Instance counter = 1 (ctor)
Delete A
    Instance counter = 0 (dtor)
Create B
    Instance counter = 1 (ctor)
Delete B
    Instance counter = 0 (dtor)
Create new B stored as A*
    Instance counter = 1 (ctor)
Delete previous pointer
    Instance counter = 0 (dtor)
Create C
    Instance counter = 1 (ctor)
    C says hi!
Delete C
    C says bye!
    Instance counter = 0 (dtor)  // We exit main() now
    C says bye! 
    Instance counter = -1 (dtor)
    Instance counter = -2 (dtor)
    Instance counter = -3 (dtor)
Run Code Online (Sandbox Code Playgroud)

Q2:任何认为不是遗传的人都可以解释一下吗?

问题3:那么当您使用输入调用子类的构造函数时会发生什么?是否也称为超类的"空构造函数"?

Kos*_*Kos 36

术语,术语......

好的,"Foo是继承的"是什么意思?我们的意思是,如果类的对象A必须Foo在其接口,那么该类的对象B是的子类A也有Foo在其接口.

  • 构造函数不是对象接口的一部分.它们直接属于类.类AB可以提供完全不同的构造函数集.这里没有"被继承".

    (实现细节:每个B的构造函数调用一些A的构造函数.)

  • 析构函数确实是每个对象接口的一部分,因为对象的用户负责调用它们(即直接使用delete或间接使对象超出范围).每个对象只有一个析构函数:它自己的析构函数,可以选择是虚函数.它始终是它自己的,它不是遗传的.

    (实现细节:B的析构函数调用A的析构函数.)

所以:基础构造函数和析构函数之间存在连接,但它不像"它们是继承的".

我希望这能回答你的想法.


Oli*_*rth 7

Q1:我从实践中也知道的是,如果没有显式定义派生类的构造函数,你不能使用与它的父构造函数相同的原型初始化派生对象,这是正确的吗?

除了在超类中定义了默认构造函数的简单情况之外,是的,你是对的.


Q2:任何认为不是遗传的人都可以解释一下吗?

这可能是术语定义的问题.虽然很明显虚拟析构函数存在并且"按预期"工作,但我们在C++标准([class.virtual])中看到:

即使析构函数不是继承的,派生类中的析构函数也会覆盖声明为virtual的基类析构函数

(强调我的)


问题3:那么当您使用输入调用子类的构造函数时会发生什么?是否也称为超类的"空构造函数"?

如果您没有显式调用特定的超类构造函数,那么将调用默认的超类构造函数(假设它是可见的).

  • @Sh3ljohn:术语“继承”在 C++ 标准中具有非常具体的含义,与该术语的常见用法略有不同。这是差异表现出来的主要领域。C++ 标准本质上声明的是基类的析构函数不是派生类的一部分(在这个意义上它不是继承的)。但是如果涉及析构函数,虚拟调用机制仍然需要工作(所以从这个意义上说,析构函数是“继承的”) (2认同)

Pet*_*ker 5

析构函数不被继承。如果类没有定义,编译器会生成一个。对于简单的情况,析构函数仅调用基类的析构函数,这通常意味着其析构函数没有显式代码(模仿继承)。但是,如果类具有带析构函数的成员,则生成的析构函数会在调用基类的析构函数之前调用这些成员的析构函数。这是继承函数不会做的事情。