覆盖c ++虚方法

shn*_*shn 12 c++ inheritance overriding virtual-functions

我有一个类模板,其中一些方法被定义为虚拟,以使我的类的用户能够在他的派生类中为它们提供实现.请注意,在我的模板类中,有一些非虚拟方法使用虚拟方法(应该在非虚拟类中调用应该返回值的虚拟类).

你能给我一个正确代码的简单例子,其中父类的虚方法应返回一个值(但它的实现是在子类中提供的),而父类中的虚方法返回的值则用于其他该类的方法.因为我在某处看到(例如这里:安全地覆盖C++虚函数)这会导致一些问题,用户定义的方法会注意覆盖父类的虚方法.

注意:我使用g ++编译器使用Code :: Blocks编程.

编辑:根据要求,我想要一个简单的例子:

template<typename T>
class parent {
public:
  // Public methods that user can call
  int getSomething(T t);
  void putSomething(T t, int x);

  // public method that user should implement in his code
  virtual float compute(T t) { }

  // protected or private methods and attributes used internally by putSomething ...
  float doComplexeThings(...); // this can call
};
Run Code Online (Sandbox Code Playgroud)

方法compute()应该由用户(子类)实现.但是,此方法compute()由putSomething()和doComplexeThings()调用.

msc*_*der 21

您只需确保方法具有相同的签名(包括const/mutable修饰符和参数类型).如果未能覆盖子类中的函数,则可以使用纯虚拟定义来激发编译器错误.

class parent {
public:
  // pure virtual method must be provided in subclass
  virtual void handle_event(int something) = 0; 
};

class child : public parent {
public:
  virtual void handle_event(int something) {
    // new exciting code
  }
};

class incomplete_child : public parent {
public:
  virtual void handle_event(int something) const {
    // does not override the pure virtual method
  }
};

int main() {
  parent *p = new child();
  p->handle_event(1); // will call child::handle_event
  parent *p = new incomplete_child(); // will not compile because handle_event
                                      // was not correctly overridden
}
Run Code Online (Sandbox Code Playgroud)

  • @als,只允许'*covariant返回类型的小细节*',只有在函数返回引用或指针时才允许使用协变类型.我知道你知道这一点,但是我将这条评论留给其他人. (3认同)
  • @mschneider您的答案的问题是您正在强制改变语义,以避免潜在的问题.在原始情况下,该功能存在但可能会过载,在您提出的解决方案中*必须*过载.这不会在重载现有函数时解决错误,而是强制*派生类重载. (2认同)

Dav*_*eas 20

如果您可以在编译器中使用C++ 11功能,则可以使用override特殊标识符标记覆盖:

 float compute() override;
Run Code Online (Sandbox Code Playgroud)

派生类中的上述行将导致编译器错误,因为该函数不会覆盖基类中的成员函数(错误签名,缺少参数).但请注意,这必须在每个派生类中完成,它不是可以从基类强加的解决方案.

从基类中,您只能通过使函数纯虚拟来强制覆盖,但这会更改语义.它在覆盖时不会避免问题,而是在所有情况下强制覆盖.我会避免这种方法,如果你要遵循它并且有一个合理的基类型实现,使函数虚拟提供一个定义,以便派生类的实现可以只调用函数基类型(即你强制实现,但在最简单的情况下,它只会将调用转发给父母)