如何避免来自继承的属性冗余

时间:2012-04-19 09:09:50

标签: c++ class inheritance attributes

说我有这个例子:

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班:

    来自B1类的
  1. id属性
  2. 来自A类继承的name属性。
  3. 来自A1类继承B1类的另一个名称属性。
  4. 那么我该怎么做才能避免这种冗余?

2 个答案:

答案 0 :(得分: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;
}

你知道,没有一个领域可以安全地消除。 traineehousePet不同,每个name都需要单独的{{1}}。

答案 1 :(得分:1)

不,你没有任何裁员。

B类没有继承其基类中的任何成员,因为它们已被声明为私有(然后可见并且只能在它们声明的类中访问)。

例如:

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;
};

现在你这个:

  • 天体可以捕获另一个天体;
  • 天体保留了被捕物体的私人清单,因为它们可能会改变它的一些属性。
  • 行星 是一个天体。
  • 行星有一个公共(整数)属性来描述它的直径,以公里为单位。

CelestialBody的私有成员在其外部不可见(实现细节类型)。世界知道PlanetCelestialBody(由于公共继承),CelestialBody中的所有内容都是公开的Planet

如果您不想,那么您不应该只使用继承。看看这篇文章: