【问题标题】:c++ Delete inherited member variable in child classc ++删除子类中继承的成员变量
【发布时间】:2019-01-03 12:01:35
【问题描述】:

考虑以下代码:

Struct Base 
{
   int x;
   double y;    
}

Struct A : public Base
{   
}

Struct B : public Base
{  //here I don't want x (Base::x) to be inherited.
   // is there a way to delete it (something like delete Base::x)
}

Struct C : public Base
{   
}

什么是完成此类任务的最佳实践? x 应该被AC 继承(可能还有很多其他类)所以我不能把它放在Base 的私有部分。我看到的唯一方法是从Base 中删除x 并将其放入AC。但应该有另一种方式吧?谢谢。

【问题讨论】:

  • 如果B 不应该有Base::x,那么B 不应该从Base 公开继承。
  • 如果B 不需要x,为什么它是Base?也许你有一个“BaseX”和“BaseY”的概念正在努力实现。或者也许它们应该在需要时被包含,而不是继承?
  • 顺便说一句:为什么投反对票?
  • @doctorlove 考虑一个基类RestaurantBase,其中有一个成员m_teaspoon。每个餐厅类(Struct ItaliaFood {}Struct FrenchFood {} 等)都继承自 RestaurantBase。现在有一些日本餐厅(Struct JapanFood {}),这也是一家餐厅,但没有茶匙。所以我不希望m_teaspoon 被继承。但它是一家餐厅,应该继承RestaurantBase的其他100名成员
  • @Gaetan Read Scott Meyors Effective c++ - Item 34. 区分接口继承和实现继承。通过将茶匙作为接口的一部分,您将在基类的子类上强制执行此实现细节。考虑将工具和抽象部分作为界面的一部分。

标签: c++ inheritance


【解决方案1】:

没有办法“删除”继承的数据成员,甚至无法隐藏它们。他们得到子类的内在部分。 如果B 只继承Base 的一部分,则需要拆分Base

Struct Base 
{
   double y;    
}

Struct BaseWithX : public Base
{
   int x;
}

Struct A : public BaseWithX
{ }

Struct B : public Base
{ }

Struct C : public BaseWithX
{ }

【讨论】:

  • 感谢 Stephan,也许 c++18 应该引入这样的delete x,以允许部分继承。如果您考虑我上面提到的餐厅示例,那么创建一个新的基类只是为了防止继承单个成员变量是很烦人的
  • @Gaetan 麻烦的是,您描述的用例并没有真正遵守 OOP 的原则,因此它不太可能是该语言在其继承实现中迎合的用例。你基本上陷入了the circle-ellipse trap,但更糟糕的是:“食物”没有理由成为一种“餐厅”。
【解决方案2】:

公共继承建立is-a 关系。这意味着B Base。这意味着如果Base 拥有x,那么由于B BaseB 将拥有x。如果你有这个问题,你需要重新考虑这个设计。考虑将BBase 之间的关系切换为组合:

struct B {
    void some_function_using_base();
private:
    Base base_;
};

【讨论】:

  • 考虑一个基类RestaurantBase,其中有一个成员m_teaspoon。每个餐厅类(Struct ItaliaFood {}Struct FrenchFood {} 等)都继承自 RestaurantBase。现在有一些日本餐厅(Struct JapanFood {}),这也是一家餐厅,但没有茶匙。所以为此我不希望m_teaspoon 被继承。但它是一家餐厅,应该继承RestaurantBase的其他100个成员
  • @Gaetan Read Scott Meyors Effective c++ - Item 34. 区分接口继承和实现继承。通过将茶匙作为接口的一部分,您将在基类的子类上强制执行此实现细节。考虑制作utensils 并抽象出接口的一部分。
【解决方案3】:

就隐藏基类的成员而言,您可以通过从其私有继承并使用using 选择性地公开公共(或受保护)基类成员来实现:

Struct Base 
{
   int x;
   double y;    
}

Struct A : public Base
{   
}

Struct B : private Base
{  
   using Base::x; // only pull in x in the public section of the class
}

...

B b;
double y = b.y // <= compilation error here

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-08-16
    • 2012-12-25
    • 2020-08-18
    • 2019-03-25
    • 2012-05-16
    • 1970-01-01
    • 2018-11-15
    • 1970-01-01
    相关资源
    最近更新 更多