【问题标题】:Not defining Virtual method in derived class as well也没有在派生类中定义虚拟方法
【发布时间】:2017-01-12 04:05:38
【问题描述】:

我有以下类层次结构。

class A {
public:
virtual bool foo() const;
};

class B : public A {
     // Redeclare foo as virtual here?
};

class C : public B {
bool foo() const {/*Definition*/ return true;}
};

class D : public B {
bool foo() const {/*Definition*/ return false;}
};

所以类 C 和 D 想要实现的 foo() 方法,B 没有。我怎样才能做到这一点?我是否必须在 B 类中将 foo() 重新声明为虚拟?

注意:忽略这里和那里的小语法错误。这不是实际代码。我的问题只是关于概念。

【问题讨论】:

  • 您是否忘记了实际代码中类声明后的分号?这会导致问题。
  • 忽略语法错误。这不是实际的代码。我的问题是关于这个概念的。

标签: inheritance virtual derived


【解决方案1】:
  • 如果您严格希望派生类实现一个函数,则将该函数设为基类中的pure virtual function

  • 如果您只是希望随机派生类重新实现一个函数,那么只需在基类中创建函数 virtual,就像您在示例中所做的那样。

现在,由于函数 foo 是基类 class A 中的 virtual,因此将为 class A 和所有直接或间接派生自 class A 的类创建一个虚拟表 vtable

虚拟函数条目存储在vtable 中,如果在后续派生类中重新实现它们,它们只会在vtable 中被替换。

  • 所以,如果class B 重新实现foo,那么在class Bvtable 中,条目将是B::foo
  • 所以,如果class C 重新实现foo,那么在vtable 中的class C 中,条目将是C::foo

因此,class B 不需要将函数 foo 声明为 virtual

如果一个函数是virtual,那么解析将在运行时使用其对象被使用的相应类的vtable进行。

【讨论】:

    【解决方案2】:

    答案是否定的,B 不必重新实现 foo()。它继承了 A 的函数。请注意,如果您创建 B 的(堆栈分配的)实例并在其上调用 foo(),则该函数不会被视为虚拟函数——调用 A 的 foo()。 要在派生类中使用重新定义的函数的虚拟版本(利用多态性,请参阅),您必须通过指向派生类实例的指针或引用来调用函数。否则将使用对象的静态类型。

    B b;
    
    B.foo(); // calls A's foo()
    
    B* b_ptr = &b;
    b_ptr->foo(); // calls B's foo()
    
    B& b_ref = b;
    b_ref.foo(); // calls B's foo()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-21
      • 1970-01-01
      • 2011-10-29
      • 1970-01-01
      相关资源
      最近更新 更多