次の例は、本 "Inside C++ object model"からのものです。
class Abstract_base {
public:
virtual ~Abstract_base () = 0;
virtual void interface () const = 0;
virtual const char* mumble () const
{
return _mumble;
}
protected:
char *_mumble;
};
著者は、純粋な仮想基本クラスのデータメンバーである_mumble
を初期化する場合は、"保護されたコンストラクター"を実装する必要があると述べています。
しかし、なぜ保護された?そして、なぜ"パブリックコンストラクタ"はこのクラスに適していないのですか?
あなたの答えをありがとう、そして例があればそれは完璧でしょう~~ :)
とにかく基本クラスのオブジェクトを作成することは許可されていないので、それは実際には問題ではありません。 protected
にすることは、クラスが基本クラスであることになっているという事実を思い出させるためだけに機能します。それは化粧品/ドキュメンテーションだけです。
検討する
struct Base {
virtual ~Base() = 0;
protected:
Base() { std::puts("Base constructor"); }
};
Base::~Base() { std::puts("Base destructor"); }
struct Derived : Base {};
int main()
{
//Base b; // compiler error
Derived d;
Base *b = new Derived();
delete b;
}
protected
を削除しても、プログラムの意味はまったく変わりません。
コンストラクターがpublicであるかprotectedであるかは関係ありません。 抽象クラスはインスタンス化できません。
コンストラクターを呼び出すには、それを継承する必要があります。Derivedクラスは、のコンストラクターを呼び出すためです。抽象クラスDerivedクラスがアクセスできる限り、どの保護レベルを選択してもかまいません。
protected
にする理由の1つは、クラスを継承によって構築する必要があることを思い出させるためですが、正直なところ、クラスが純粋仮想メンバー関数。
struct B {
virtual void func () = 0;
virtual ~B () = 0 { };
};
B::~B () { }
struct D : B {
void func () override;
};
int main () {
B b; // will error, no matter if Bs ctor is 'public' or 'protected'
// due to pure virtual member-function
D d; // legal, D has overriden `void B::func ()`
}
純粋仮想クラスはインスタンス化できないため、コンストラクターがパブリックであるか保護されているかは関係ありません。
パブリックコンストラクターは構文的に正しい。ただし、保護することで、クラスをインスタンス化できないことを示すより強力なことがわかります。
#include <iostream>
using namespace std;
class PublicAbstract {
public:
PublicAbstract() { }
virtual void doThings() =0;
};
class ProtectedAbstract {
protected:
ProtectedAbstract() { }
public:
virtual void doMoreThings() =0;
};
class B: public PublicAbstract {
public:
void doThings() { }
};
class C: public ProtectedAbstract {
public:
void doMoreThings() { }
};
int main() {
B b;
C c;
return 0;
}
抽象クラスはそもそもインスタンス化できないため、パブリックコンストラクタはあまり役に立ちません。
保護されたコンストラクターは理にかなっています。このようにして、派生した具象クラスは、基本抽象クラスの保護されたコンストラクターにチェーンする独自のパブリックコンストラクターを提供できます。
Protecetd ctorは、ctorがAbstract_base
から派生したクラスによってのみ呼び出されるようにします。
Public ctorクラスにはpure virtual
メソッドが含まれているため、適切ではありません。子クラスを介さない場合、純粋仮想クラスをどのようにインスタンス化する予定ですか?