web-dev-qa-db-ja.com

派生クラスコンストラクターから基本クラスコンストラクターを呼び出す

質問があります:

もともと私が変更できないこれらのクラスを持っているとしましょう(私が使用しているライブラリから取得されているためです):

class Animal_
{
public:
    Animal_();
    int getIdA()
    {
        return idA;
    };
    string getNameA()
    {
        return nameA;
    }
private:
    string nameA;
    int idA;
}

class Farm
{
public :
    Farm()
    {
        sizeF=0;
    }
    Animal_* getAnimal_(int i)
    {
        return animals_[i];
    }
    void addAnimal_(Animal_* newAnimal)
    {
        animals_[sizeF]=newAnimal;
        sizeF++;
    }

private:
    int sizeF;
    Animal_* animals_[max];
}

しかし、その後、フィールドをいくつか追加するだけのクラスが必要だったので、次のようにしました。

class PetStore : public Farm
{
public :
    PetStore()
    {
     idF=0;
    };
private:
    int idF;
    string nameF;
}

しかし、派生クラスを初期化することはできません。この継承を行ったので、PetStoreに動物を追加できますが、sizeFはプライベートなので、どうすればそれを行うことができますか? PetStoreのデフォルトコンストラクターでFarm()を呼び出すことができるのではないかと考えています。

25
Joy

PetStoreのコンストラクターは、Farmのコンストラクターを呼び出します。それを防ぐ方法はありません。何もしなければ(あなたがやったように)、デフォルトのコンストラクタ(Farm())を呼び出します。引数を渡す必要がある場合は、初期化子リストで基本クラスを指定する必要があります。

PetStore::PetStore()
    : Farm( neededArgument )
    , idF( 0 )
{
}

(同様に、PetStoreのコンストラクターはnameFのコンストラクターを呼び出します。クラスのコンストラクターalwaysは、そのすべての基本クラスおよびそのすべてのコンストラクターを呼び出しますメンバー。)

61
James Kanze

まず、PetStoreはファームではありません。

しかし、これを乗り越えましょう。実際にはプライベートメンバーにアクセスする必要はありません。パブリックインターフェイスには必要なものがすべて揃っています。

Animal_* getAnimal_(int i);
void addAnimal_(Animal_* newAnimal);

これらは、アクセスを許可されているメソッドであり、使用する必要があるメソッドです。

つまり、PetStoreに動物を追加できるようにこの継承を実行しましたが、sizeFはプライベートなので、どうすればそれを実行できますか?

簡単に、addAnimalを呼び出します。 publicであり、sizeFもインクリメントします。

また、

PetStore()
{
 idF=0;
};

と同等です

PetStore() : Farm()
{
 idF=0;
};

つまり、基本コンストラクタが呼び出され、基本メンバーが初期化されます。

13
Luchian Grigore

基本クラスコンストラクターは、派生クラスコンストラクターによって既に自動的に呼び出されます。 C++では、基本クラスにデフォルトコンストラクターがあり(引数を取らず、コンパイラーが自動生成できます!)、派生クラスコンストラクターが初期化リスト内の別の基本クラスコンストラクターを呼び出さない場合、デフォルトコンストラクターは呼ばれる。つまりあなたのコードは次と同等です:

class PetStore: public Farm
{
public :
    PetStore()
    : Farm()     // <---- Call base-class constructor in initialision list
    {
     idF=0;
    };
private:
    int idF;
    string nameF;
}
5
Michael Wild

しかし、派生クラスを初期化することはできません。つまり、この継承を行ったので、PetStoreに動物を追加できますが、sizeFはプライベートなので、どうすればそれを行うことができますか?だから、PetStoreのデフォルトコンストラクターでFarm()を呼び出すことができるのではないかと考えています。

パニックにならないでください。

ファームコンストラクターは、PetStoreのコンストラクターで自動的に呼び出されます

基本クラスの継承呼び出し規則を参照してください。 スーパークラスコンストラクターを呼び出すための規則は何ですか?

2
Klaim