覆盖c ++虚方法

时间:2012-01-26 12:26:49

标签: c++ inheritance override virtual-method

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

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

注意:我使用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
};

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

3 个答案:

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

答案 1 :(得分:20)

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

 float compute() override;

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

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

答案 2 :(得分:0)

这个问题是在2013年提出来的。它已经很老了,但我找到了一些在答案中不存在的新内容。

我们需要了解三个概念:重载覆盖隐藏

简短回答,您希望从基类重载继承函数。 但是,重载是为函数添加多个行为的机制,它需要在相同规模下的所有这些函数。但虚拟函数显然属于Base类。

class A {
public:
  virtual void print() {
    cout << id_ << std::endl;
  }
private:
  string id_ = "A";
};

class B : A {
public:
  using A::print;
  void print(string id) {
    std::cout << id << std::endl;
  }
};

int main(int argc, char const *argv[]) {
  /* code */
  A a;
  a.print();
  B b;
  b.print();
  b.print("B");
  return 0;
}
  

在您的derive类中使用A :: print; 添加将完成工作!

虽然我认为这不是一个好主意,因为重载继承背后的哲学是不同的,将它们嵌套在一起可能不是一个好主意。< / p>