明确停止后期绑定

时间:2017-06-05 13:11:50

标签: c++

如果我们创建一个指向基类类的对象指针,该对象指向其子类对象,那么我们使用虚拟关键字进行后期绑定 所以,在后期绑定的情况下,我们的代码如下: -

#include<iostream>
using namespace std;
struct A{
    virtual void print() {
        cout<<"function1";
    }
};

struct B : public A{
    void print(){
        cout<<"function2";
    } 
};

struct C : public B{
    void print(){
        cout<<"function3";
    } 
};

int main(){
    A* a = new C();
    A* p = new B();
    a->print();
    p->print();
} 

现在我的问题是:当我们在基类中使用虚拟关键字时,在基类中创建的派生类的所有函数都将变为虚函数。       在多级继承中,有什么办法可以阻止类c的函数被虚拟化?    有什么方法可以打破这个虚拟功能链?   对不起有任何错误,但我尽我所能..☺️☺️

1 个答案:

答案 0 :(得分:1)

无法在子类中创建已virtual不是virtual的函数。

虚拟性是顶级基类的属性,而不是子类。一旦方法被标记为virtual,并且指向该类的指针在调用时必须使用该函数的动态调度,因为指针可能指向已覆盖该行为的子类。

考虑以下代码:

A a;
B b;
C c;

A * ap = &a;
A * bp = &b;
A * cp = &c;

ap->print(); // 'function1'
bp->print(); // 'function2'
cp->print(); // 'function3'

这里,对print的调用不能告诉在编译时调用哪个函数,它们绝对必须使用动态调度。

但是,您可以使C::print的行为与A::print

相同
struct C : public B {
    void print() {
        A::print();
    }
};

结果是:

ap->print(); // 'function1'
bp->print(); // 'function2'
cp->print(); // 'function1'

如果A::print()的行为发生变化,C::print()会反映这些变化。

但是,除非您使用下面列出的final关键字,否则仍然可以覆盖。

原始回答:

我相信您正在寻找final说明符。 它仅在C ++ 11中可用。

引用en.cppreference关于final specifier

的页面
  

在虚函数声明或定义中使用时,最终   确保该函数是虚函数并指定它可能不是   被派生类重写。该计划形成不良(a   否则会生成编译时错误。

他们提供的示例的变体,演示了您的问题的解决方案:

struct A
{
    virtual void foo();
};

struct B : A
{
    void foo() final; // B::foo is overridden and it is the final override
};

struct C : B
{
    void foo() override; // Error: foo cannot be overridden as it's final in B
};