なぜC++には仮想コンストラクターが存在しないのか?
仮想機構が機能するための前提条件
C++における仮想(virtual)機構は、「基底クラスのポインタが派生クラスのオブジェクトを指している」という状況でのみ動作します。この仕組みを理解することが、仮想コンストラクターに関する議論を理解する第一歩となります。
コンストラクターをvirtualにできない理由
C++では、コンストラクターを仮想関数にすることはできません。その理由は、クラスのコンストラクターが実行される時点では、メモリ上に仮想関数テーブル(vtable)がまだ作成されておらず、仮想関数へのポインタ(vptr)も定義されていないためです。
仮想関数の仕組みはvtableとvptrに依存していますが、これらはオブジェクトの生成過程で設定されます。ところがコンストラクターは、まさにその「オブジェクト生成の最中」に呼び出されるため、仮想機構を利用できる状態にありません。したがって、コンストラクターは常に非仮想(non-virtual)である必要があります。
仮想デストラクターは可能
一方で、デストラクターをvirtualにすることは可能であり、実際に推奨される場面も多くあります。特に、基底クラスのポインタ経由で派生クラスのオブジェクトをdeleteする場合、デストラクターがvirtualでないと未定義動作となり、派生クラスのデストラクターが呼び出されない恐れがあります。以下に具体例を示します。
サンプルコード
#include<iostream>
using namespace std;
class b {
public:
b()
{ cout<<"Constructing base \n"; }
virtual ~b()
{ cout<<"Destructing base \n"; }
};
class d: public b {
public:
d()
{ cout<<"Constructing derived \n"; }
~d()
{ cout<<"Destructing derived \n"; }
};
int main(void) {
d *derived = new d();
b *bptr = derived;
delete bptr;
return 0;
}
実行結果
Constructing base Constructing derived Destructing derived Destructing base
実行結果の解説
このプログラムでは、まず基底クラスbのコンストラクターが呼ばれ、続いて派生クラスdのコンストラクターが呼ばれます。そしてdelete bptr;によってオブジェクトを破棄する際、デストラクターがvirtualとして宣言されているため、基底クラスのポインタ経由でも派生クラスのデストラクターが正しく呼び出され、その後基底クラスのデストラクターが実行されます。
もしデストラクターがvirtualでなければ、「Destructing derived」の出力が行われず、派生クラスが保持するリソースが解放されないままになるなど、メモリリークをはじめとする深刻な問題を引き起こす可能性があります。ポリモーフィズムを活用したクラス階層を設計する際は、必ず仮想デストラクターを宣言するようにしましょう。
-
C#にグローバル変数が存在しない理由とは?スコープ解決演算子の役割を解説
C#には、C++のような「グローバル変数」の概念が存在しません。その代わり、C++でグローバル変数の参照に使われていたスコープ解決演算子(::)は、名前空間(namespace)との関連で使用される仕組みになっています。これを「global名前空間エイリアス」と呼びます。 global名前空間エイリアスとは? 異なる名前空間で同じ識別子を持つ型が存在する場合、どちらの型を参照したいのかを明確に区別する必要があります。そんなときに活躍するのが、スコープ解決演算子を使ったglobal名前空間エイリアスです。 たとえば、System.Consoleクラスを参照したい場合、次のように記述します。 gl
-
Chromeでプロセスが大量に実行されるのはなぜ?原因と削減方法を徹底解説
Google Chromeを使いながらタスクマネージャーを開いたことがあるなら、バックグラウンドで驚くほど多くのプロセスが動いていることに気づいたかもしれません。開いているタブが2〜3個しかないのに、タスクマネージャーにはそれ以上の数のChromeのエントリが表示されます。これらはすべて、ブラウザに関連付けられたプロセスです。この記事では、Chromeが多数のプロセスを実行することがメリットなのかデメリットなのかを解説し、プロセス数を減らす具体的な方法をご紹介します。Chromeのプロセスをタスクマネージャーで確認する方法タスクマネージャーは、パソコンのパフォーマンス向上やOSのトラブルシュー