web-dev-qa-db-ja.com

純粋な仮想クラスのコンストラクター関数は「保護」または「公開」する必要がありますか?

次の例は、本 "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を初期化する場合は、"保護されたコンストラクター"を実装する必要があると述べています。

しかし、なぜ保護された?そして、なぜ"パブリックコンストラクタ"はこのクラスに適していないのですか?

あなたの答えをありがとう、そして例があればそれは完璧でしょう~~ :)

9
Wizmann

とにかく基本クラスのオブジェクトを作成することは許可されていないので、それは実際には問題ではありません。 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を削除しても、プログラムの意味はまったく変わりません。

6
Fred Foo

抽象クラスとそのような構築

コンストラクターが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 ()`
}

純粋仮想クラスはインスタンス化できないため、コンストラクターがパブリックであるか保護されているかは関係ありません。

パブリックコンストラクターは構文的に正しい。ただし、保護することで、クラスをインスタンス化できないことを示すより強力なことがわかります。

例: http://ideone.com/L66Prq

#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;
}
3
jsantander

抽象クラスはそもそもインスタンス化できないため、パブリックコンストラクタはあまり役に立ちません。

保護されたコンストラクターは理にかなっています。このようにして、派生した具象クラスは、基本抽象クラスの保護されたコンストラクターにチェーンする独自のパブリックコンストラクターを提供できます。

2

Protecetd ctorは、ctorがAbstract_baseから派生したクラスによってのみ呼び出されるようにします。

Public ctorクラスにはpure virtualメソッドが含まれているため、適切ではありません。子クラスを介さない場合、純粋仮想クラスをどのようにインスタンス化する予定ですか?

0
CinCout