[C ++詳細分析] 41.コンストラクター、デストラクターを仮想関数にすることはできますか?

1コンストラクタを仮想関数にすることはできません。デストラクタを仮想関数にすることができます

コンストラクターを仮想関数にすることはできません

  • コンストラクターの実行後、仮想関数テーブルポインターを適切に初期化できます

デストラクタは仮想関数になることができます

  • クラスを設計するときは、デストラクターを仮想関数として宣言することをお勧めします

プログラミング実験:構築、解体、仮想関数

// 41-1.cpp
#include<iostream>
using namespace std;
class Base
{
public:
    Base()
    {
        cout << "Base()" << endl;
    }
    virtual ~Base()
    {
        cout << "~Base()" << endl;
    }
};
class Derived : public Base
{
public:
    Derived()
    {
        cout << "Derived()" << endl;
    }
    virtual ~Derived()
    {
        cout << "~Derived()" << endl;
    }
};
int main()
{
    Base* p = new Derived();
    delete p;
    return 0;
}

親クラスのポインターがサブクラスのオブジェクトを指すnew Derived();サブクラスのオブジェクトを作成すると、親クラスのコンストラクターが呼び出され、サブクラスのコンストラクターが呼び出されます。デストラクタが仮想関数でない場合、pは親クラスのポインターです。親クラスのデストラクタを呼び出しますが、サブクラスのコンストラクタは呼び出しません。
デストラクタは仮想関数として定義されます。ポリモーフィック属性に従って、ポイントされたオブジェクトが破棄されます。サブクラスDerivedが破棄されると、サブクラスデストラクタが最初に呼び出され、次に親クラスデストラクタが呼び出されます。

コンパイルして実行:

$ g++ 41-1.cpp -o 41-1
$ ./41-1
Base()
Derived()
~Derived()
~Base()

2仮想関数を呼び出すデストラクタを作成しても、ポリモーフィズムは発生しません

コンストラクターにポリモーフィックな動作はありません

  • コンストラクターを実行すると、仮想関数テーブルポインターが正しく初期化されません。

デストラクタにポリモーフィックな動作はありません

  • デストラクタが実行されると、仮想関数テーブルポインタが破棄されました

したがって、コンストラクタとデストラクタでポリモーフィックな動作は発生せず、現在のクラスで定義されている関数バージョンのみが呼び出されます。

ウィル

// 41-2.cpp
#include<iostream>
using namespace std;
class Base
{
public:
    Base()
    {
        cout << "Base()" << endl;
        func();								// 调用虚函数
    }
    virtual void func()						// 增加虚函数
    {
        cout << "Base::func()" << endl;
    }
    virtual ~Base()
    {
        func();								// 调用虚函数
        cout << "~Base()" << endl;
    }
};
class Derived : public Base
{
public:
    Derived()
    {
        cout << "Derived()" << endl;
        func();								// 调用虚函数
    }
    virtual void func()						// 增加虚函数
    {
        cout << "Derived::func()" << endl;
    }
    virtual ~Derived()
    {
        func();								// 调用虚函数
        cout << "~Derived()" << endl;
    }
};
int main()
{
    Base* p = new Derived();
    delete p;
    return 0;
}

コンパイルして実行します。コンストラクタとデストラクタでポリモーフィックな動作は発生せず、現在のクラスで定義されている関数バージョンのみを呼び出します

$ g++ 41-2.cpp -o 41-2
$ ./41-2
Base()
Base::func()
Derived()
Derived::func()
Derived::func()
~Derived()
Base::func()
~Base()

3まとめ

1.コンストラクターを仮想関数にすることはできず、デストラクターを仮想関数にすることもできます
2.コンストラクターとデストラクターの両方が多態性を生成することはできません。

298件のオリジナル記事を公開 181 件を賞賛 100,000回以上の閲覧

おすすめ

転載: blog.csdn.net/happyjacob/article/details/104485667