有没有办法阻止在派生类的实例上调用基类方法?

时间:2014-02-20 22:01:16

标签: c++ derived-class

我有一个带有一堆功能的基类和一个扩展该类的派生类,但是基类中有一些方法对派生类没有意义。

是否可以采取措施防止派生类使用这些方法?

Class A
{
   ...

   public:
      void SharedMethod();
      virtual void OnlyMakesSenseOnA();
}

Class B : public Class A
{
   ...

   public:
      void OnlyMakesSenseOnB();
}

以下显然不起作用,但可以做类似的事情,以便编译器不允许调用某个基类方法吗?

Class B : public Class A
{
   ...

   public:
      void OnlyMakesSenseOnA() = 0;
}

4 个答案:

答案 0 :(得分:4)

这并不像我希望的那样容易回答,但同事建议这种情况表明设计不好,我应该通过添加一个只包含共同点的新基类重新思考我的继承结构功能性:

Class Base
{
   ...

   public:
      void SharedMethod();
}

Class A : public Base
{
   ...

   public:
      void OnlyMakesSenseOnA();
}

Class B : public Base
{
   ...

   public:
      void OnlyMakesSenseOnB();
}

编辑:感谢@David for providing a name我想要破解的规则。 B不是"Behavioural Subtype" of A because it fails the "counterfeit test"。因此,从A派生B违反了Liskov Subtitution Principle

根据this slide deck,假冒测试如下:

  • 假设我答应给你一个T类的对象,但是 相反,我给你一个类S的对象x。
  • 您可以将x置于您喜欢的任何系列方法调用中 (从T的签名中选择)。
  • 如果x的行为方式不是T对象的预期, 然后你知道它是伪造品,x未通过测试。
  • 如果所有S对象总是通过每个假冒测试,那么S是 T.的行为子类型。

答案 1 :(得分:4)

不,这是完全错误。如果成员函数在派生类型中不可调用,那么您将破坏Liskov替换原则。考虑这是否是正确的继承关系。您可能希望将SharedMethod提取到真实基础,并提供两种不相关的AB类型。

答案 2 :(得分:2)

如果在派生类上调用了无效方法,您也可以抛出异常。它不会在编译时捕获错误,但至少可以防止它意外地被用作运行时。

Class B : public Base
{
   ...

   public:
      void OnlyMakesSenseOnA() { throw Exception(); }
}

答案 3 :(得分:0)

是的,如果我们正在谈论外部呼叫,这是可能的并且非常简单。您可以使用派生类的私有方法隐藏父级的方法。也可以使用静态方法。

在cpp 98、11、14上进行了测试。在C++ shell中尝试一下。


class Base{
public:
  void methodBase(){};
  static void methodBaseStatic(){};
};

class Derived : public Base{
//private: //(private on default)
  void methodBase(){};
  static void methodBaseStatic(){};
};

正常操作:

int main()
{
  Base b;
  
  b.methodBase();
  Base::methodBaseStatic();
  
  Derived d;

  return 0;
}

编译错误

int main()
{
  Derived d;
  
  d.methodBase();
  
  Derived::methodBaseStatic();
  
  return 0;
}