*あなた*はC ++ ABCコンストラクターを何のために使用しますか?
-
19-08-2019 - |
質問
この分野の人々は、C ++の抽象基本クラスコンストラクタを現場で何に使用していますか?私は、データメンバーも非純粋な仮想メンバーもない純粋なインターフェイスクラスについて話している。
ABCコンストラクターを便利な方法で使用するイディオムを誰でも実証できますか?それとも、ABCを使用して、空、インライン、および保護されたままのインターフェイスを実装するという性質に本質的ですか?
解決
ABCコンストラクターを便利な方法で使用するイディオムを誰でも実証できますか?
ここに例がありますが、これは不自然で珍しい例です。
すべてのインスタンスのリストを保持するために使用できます:
class IFoo
{
private:
//static members to keep a list of all constructed instances
typedef std::set<IFoo*> Set;
static Set s_set;
protected:
//new instance being created
IFoo()
{
s_set.insert(this);
}
public:
//instance being destroyed
virtual ~IFoo()
{
s_set.remove(this);
}
... plus some other static method and/or property
which accesses the set of all instances ...
};
または、ABCを使用して、空、インライン、および保護されたままのインターフェースを実装するという性質に本質的なのですか?
通常、それらはまったく宣言されていません!それらを宣言する理由はありません:
- 空でインライン= <!> gt;なぜわざわざ宣言するのですか?
- Protected = <!> gt; ABCにはおそらくいくつかの pure virtual メソッドが既にあるため、サブクラスとして以外は既にインスタンス化できません。
他のヒント
すべての派生クラスに共通の動作があると仮定します。外部レジストリに自分自身を登録したり、何かの有効性をチェックしたりするなど。
この共通コードはすべて基本クラスのコンストラクターに配置でき、各派生クラスのコンストラクターから暗黙的に呼び出されます。
どのように抽象基底クラスのコンストラクタをどのように使用するか ?
抽象基本クラスBと派生クラスDがあるとします。タイプDのオブジェクトが作成されると、Bのコンストラクターが最初に呼び出されますが、その時点でオブジェクト<!> quot; is <!> quot;タイプBのまま(こちらを参照)-特に、Bのコンストラクターの本体から仮想関数を呼び出すと、それらの関数の B自身の実装が呼び出されます。ただし、Bが純粋な抽象クラスの場合、これらの仮想関数はいずれも定義されていないため、プログラムはすぐにクラッシュします。
Bのコンストラクターが仮想関数の最も派生したクラス(Dなど)の実装を呼び出すことを意図していたと思いますか? Dのオブジェクトはまだ完全には構築されていないため、一般にこれは悪い考えです。したがって、Dの仮想関数の実装内からDのメンバー変数にアクセスすると、初期化されていないメモリにアクセスします。
覚えておいてください: <!> quot;リソースの取得は初期化<!> quot; 。
ロックのメカニズムの一種として抽象基底クラスを使用する場合があります。たとえば、複数のスレッドが単一のリソースを共有する必要があるマルチスレッド環境では、スレッドはコンストラクタを使用してリソースを取得し、デストラクタを使用してリソースを解放できます
void PlayWithPaintBallGun(Target &target)
{
PaintBallGun paintBallGun; // constructor waits until the gun is free,
// then picks it up.
paintBallGun.Aim(target); // Shoot something
paintBallGun.Fire(); //
// Clever! The destructor is automatically
// called when it goes out of scope. So we
// can't forget to put the gun down.
}
ヒューゴ
多くの有用な例を考えることはできません。データメンバーのないクラスには状態がないため、何も初期化できません。ただし、コンストラクタ/デストラクタにログを記録させることができます。たとえば、すべての訪問者オブジェクトの作成/破棄を記録するには:
class Visitor {
public:
Visitor() {
std::cout << "Visitor@" << this << " created"
<< std::endl;
}
virtual ~Visitor() {
std::cout << "Visitor@" << this << " destroyed"
<< std::endl;
}
virtual void visitA(A*) = 0;
virtual void visitB(B*) = 0;
// ...
};
通常は、メンバーを適切な値に初期化することのみを目的としています。