編集: 回答の要約
以下では、B は A のサブクラスです。
それは用語の問題です。俳優と脚本家はない継承されるという意味で、Bのctor/dtorはないA のインターフェースから借用できます。クラスには少なくとも 1 つのコンストラクタがあり、正確に 1 つのデストラクタがあります。
- コンストラクター:
- B は A からコンストラクタを継承しません。
- Bのコンストラクタが明示的に呼び出しを行わない限りの一つAのコンストラクタの場合、Aのデフォルトコンストラクタが自動的に呼び出されます。前にB の ctor 本体 (B が作成される前に A を初期化する必要があるという考え方)。
- デストラクタ:
- B は A の dtor を継承しません。
- 後終了すると、B のデストラクタは自動的に A のデストラクタを呼び出します。
謝辞:特に Oli Charlesworth 氏と Kos 氏の回答に感謝したいと思います。Kos 氏の回答が最も理解しやすかったため、これを解決策として設定しました。
オリジナル投稿
Google で「C++ デストラクタ継承 site:stackoverflow.com」を検索すると、現在次の投稿が見つかります。
- コンストラクタとデストラクタの継承: 30,000以上の評判を持つ2人のユーザーは、継承されていると言い、そうではないと言っている。
- 仮想デストラクタは継承されますか?: ここではデストラクタが継承されないことを示すようなことは何も述べられていない
- C++ のデストラクタと継承?: コメントはデストラクタが継承されることを示しているようだ
質問1:私が実践から知っていることとしては、派生クラスのコンストラクターを明示的に定義せずに、派生オブジェクトをその親コンストラクターと同じプロトタイプで初期化することはできないということですが、これは正しいでしょうか?
デストラクタが継承されるように見えることは投稿からかなり明らかですが、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();
}
出力は次のとおりです (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)
質問2:遺伝しないと考えている人は説明してもらえますか?
質問3:では、入力を使用してサブクラスのコンストラクターを呼び出すと何が起こるでしょうか? スーパークラスの「空のコンストラクター」も呼び出されるのでしょうか?
ベストアンサー1
用語、用語...
A
さて、「Foo は継承される」とはどういう意味でしょうか? クラスのオブジェクトがそのインターフェースに を持っている場合、のサブクラスであるFoo
クラスのオブジェクトもそのインターフェースに を持っていることを意味します。B
A
Foo
コンストラクターオブジェクトのインターフェースの一部ではありません。クラスに直接属します。クラス
A
はB
完全に異なるコンストラクタのセットを提供する場合があります。ここでは「継承」されません。(実装の詳細: 各 B のコンストラクターは、いくつかの A のコンストラクターを呼び出します。)
デストラクタ実際、それらは各オブジェクトのインターフェースの一部です。オブジェクトのユーザーがそれらを呼び出す責任があるからです (つまり、直接的に、
delete
またはオブジェクトをスコープ外にすることで間接的に)。各オブジェクトにはデストラクタが1つだけあります: 独自のデストラクタ。オプションで仮想デストラクタになることもあります。常に独自のデストラクタであり、継承されません。(実装の詳細: B のデストラクタが A のデストラクタを呼び出します。)
つまり、基本および派生のコンストラクターとデストラクタの間には接続がありますが、「継承されている」わけではありません。
これがあなたの考えに対する答えになれば幸いです。