【问题标题】:Calling Pure Virtual Function From Abstract Base Class Member Function?从抽象基类成员函数调用纯虚函数?
【发布时间】:2013-06-29 06:15:23
【问题描述】:

所以,根据粗略的搜索,我已经知道从构造函数调用虚函数(无论是纯的还是其他的)是不行的。我已经重组了我的代码以确保我没有这样做。虽然这会导致我的类的用户在他们的代码中添加一个额外的函数调用,但这真的没什么大不了的。也就是说,他们现在不是在循环中调用构造函数,而是调用函数,这(实际上!)提高了代码的性能,因为我们没有每次都构建和销毁相关对象的内务管理。

但是,我偶然发现了一些有趣的东西......

在抽象类中我有这样的东西:

// in AbstractClass.h:
class AbstractClass {
 public:
  AbstractClass() {}
  virtual int Func(); //user can override
 protected:
  // Func broken up, derived class must define these
  virtual int Step1() = 0;
  virtual int Step2() = 0;
  virtual int Step3() = 0;
// in AbstractClass.cpp:
int AbstractClass::Func() {
  Step1();
  // Error checking goes here
  Step2();
  // More error checking...
  // etc...
}

基本上,纯虚函数大部分时间都遵循一个通用结构,但如果它们不遵循,Func() 是虚拟的,并允许派生类指定顺序。但是,每个步骤都必须在派生类中实现。

我只是想确定我在这里没有做错任何事情,因为 Func() 函数调用了纯虚拟函数。也就是说,使用基类,如果调用 StepX(),就会发生不好的事情。但是,通过创建派生对象然后在派生对象上调用 Func()(例如 MyDerivedObject.Func();)来使用该类,应该正确地重载所有纯虚函数。

按照这种方法,我有什么遗漏或做错了吗?感谢您的帮助!

【问题讨论】:

  • 这是使用Non-Virtual Interface idiom实现Template Method pattern的教科书示例。
  • 澄清一下,“在构造函数中调用虚函数”和“调用纯虚函数”之间有很大的区别。前者棘手且令人沮丧(尽管有效),后者完全是错误的(而且也并非完全微不足道)。
  • 在构造函数或析构函数中调用虚函数并不是“不行”,除非你没有费心去理解它们是如何工作的。
  • @PeteBecker 这是我正在研究的答案。 stackoverflow.com/questions/962132/… 并不是我没有费心去学习它们是如何工作的,我对 OOP 方面还是很陌生。

标签: c++ inheritance virtual-functions pure-virtual


【解决方案1】:

Func 调用的是虚拟的,而不是纯虚拟的。您必须使用范围运算符限定调用,即 AbstractClass::Step1() 才能调用 THAT(虚拟纯)函数。既然你不是,你总是会得到派生类的实现。

【讨论】:

  • 所以无论我做什么,除非我做一些像 AbstractClass::Step3() 这样的真正 hacky,否则这些函数将被派生类覆盖?对于良好的 C++ 代码实践,这种方法是否有任何危险信号?
  • 实际上,这正是 OO 和 C++ 强大的原因。您可以编写派生类指定详细信息的“程序”。考虑一个通信协议。建立连接(); while(!Done()) {SendRequest(); GetResponse();} TerminateConnection();所有这些方法都可以是“虚拟的”,一个派生类使用 TCP,另一个使用更高级别的“连接”机制,或者更简单的点对点 RS-232 协议在它们的建立/终止会话()方法中没有任何内容。然而,您定义了一个可以轻松实现和扩展的小型框架。
  • 感谢您的解释。我对其中一些 OO 概念还很陌生,我想尽可能地敏锐......
【解决方案2】:

基类中的虚函数使派生类能够覆盖它。但似乎事情到此为止了。

但是如果基类虚函数是纯的,那会强制派生类实现该函数。

【讨论】:

    【解决方案3】:

    作为旁注,您可以将 Step1、Step2、Step3 方法设为私有,这样编译器就会阻止您直接调用它们。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-06-19
      • 2015-08-05
      • 2019-04-20
      • 2012-01-27
      • 2011-03-21
      • 2014-01-04
      相关资源
      最近更新 更多