关于继承:覆盖c ++虚方法

override c++ virtual method

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

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

注意:我使用g++编译器用code::blocks编程。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
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()是由putshing()和docomplexthings()调用的。


如果可以在编译器中使用C++ 11特性,那么可以用EDCOX1×0的特殊标识符将重写标记为:

1
 float compute() override;

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

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


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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
}


这个问题是在2013年提出的。它很旧,但我发现了一些新的东西,这些东西在答案中不存在。

我们需要理解三个概念:过载、覆盖和隐藏。

简而言之,您希望从基类重载继承函数。但是,重载是一种为函数添加多个行为的机制,它需要在相同的尺度下使用所有这些函数。但虚拟函数显然在基类中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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;
}

Add using A::print; in your derive class will do the work!

尽管我觉得这不是一个好主意,因为过载和继承背后的哲学是不同的,把它们套在一起可能不是一个好主意。