1

私はこの例を持っていると言います:

class A1
{
    private:
    string name;
}

class A
{
    private:
    A1* field;
}
class B1 : public A1
{
    private:
    int id;
}
class B : public A
{
    private:
    B1* field;
}

したがって、この場合、Bクラスには次のようになります。

  1. B1 クラスの id 属性
  2. クラス A の継承に由来する name 属性。
  3. クラス A1 からの B1 クラスの継承から生じる別の名前属性。

では、この冗長性を回避するにはどうすればよいですか?

4

2 に答える 2

2

ここには冗長性は見られません。クラスの名前をより便利なものに変更しましょう。

class Animal // A1
{
    private:
    string name;
}

class Person // A
{
    private:
    Animal* housePet;
}
class Dog : public Animal // B1
{
    private:
    int breedId;
}
class DogTrainer : public Person // B
{
    private:
    Dog* trainee;
}

ご覧のとおり、安全に消去できるフィールドはありません。はtraineeと同じではありません。housePetそれぞれに個別の が必要nameです。

于 2012-04-19T09:24:52.963 に答える
1

いいえ、冗長性はありません。

Bclass は、プライベートとして宣言されているため、基本クラスからメンバーを継承しませんでした (宣言されているクラス内からのみ表示およびアクセスできます)。

例えば:

class A
{
 private:
  int _privateMember;

 protected:
  int _protectedMember;

 public:
  int _publicMember;
};

class B : public A
{
 void test()
 {
  // This doesn't work, this field is private to the class
  // where it has been declared (A)
  _privateMember = 1;

  // This works, a protected member is accessible inside the class
  // where it's declared and derived classes.
  _protectedMember = 1;

  // This works, a public member is always visible and accessible.
  _publicMember = 1;
 }
};

void test()
{
 A a;

 // This doesn't work, a private field isn't accessible outside the class
 // where it has been declared
 a._privateMember = 1;

 // This doesn't work, a protected member is accessible only inside the class
 // where it has been declared and its derived classes
 a._protectedMember = 1;

 // This works, a public member is always visible.
 a._publicMember = 1;
}

物事はこれよりも複雑になる可能性があります。たとえば、パブリック継承を常に使用する必要はありません。

class C : protected A
{
};

void test()
{
 C c;

 // This doesn't work! Field is public for its class but C has inherited from A
 // in a protected way (so only derived classes know that it derives from A).
 c._publicMember = 1;
}

friendさらに、次の宣言を使用して、クラスのすべてのプライベート メンバーを別のクラスまたは関数から見えるようにすることができます。

class D
{
 private:
  int _privateMember;

 public:
  int _publicMember;

  friend class DFriend;
};

class DFriend
{
  void test()
  {
   D d;

   // This works, public members are accessible
   d._publicMember = 1;

   // This works too, this class is a friend of D
   d._privateMember = 1;
  }
};

そうは言っても、基本クラスから派生するときは、「派生クラス 基本クラスの型です」と言うことを覚えておいてください。たとえば、いくつかのプロパティを持つ惑星を記述する基本クラスがあります (簡単にするためにパブリック フィールドとしてモデル化されています)。

class Planet
{
 public:
  int Diameter;
};

その後、突然、より一般的なものにする必要があることに気付き、CelestialBody というより一般的な基本クラスを追加します。

class CelestialBody
{
 public:
  bool canCapture(CelestialBody anotherBody)
  {
   // Some calculations
  }

 private:
  vector<CelestialBody> _capturedBodies;
};

class Planet : public CelestialBody
{
 public:
  int Diameter;
};

今、あなたはこう言います:

  • 天体とは、別の天体を捉えることができるものです。
  • 天体は、そのプロパティの一部を変更する可能性があるため、キャプチャされた天体のプライベート リストを保持します。
  • 惑星天体です。
  • 惑星には、その直径を Km で表すパブリック (整数) プロパティがあります。

のプライベート メンバーはCelestialBody、その外部には表示されません (一種の実装の詳細)。Planet世界は aが a であることを知っていますCelestialBody(公開継承のためCelestialBody) Planet

これを言いたくない場合は、単純に継承を使用しないでください。この記事を見てください:

  • 構成と継承: 別のオブジェクトから継承する場合と、別のオブジェクトをフィールドとして含める場合。
  • カプセル化 : クラス内の情報のカプセル化。
于 2012-04-19T09:12:43.403 に答える