无法理解C++`virtual`

Mik*_*ike 5 c++ virtual-functions

我无法理解virtualC++中关键字的用途.我非常了解C和Java,但我是C++的新手

来自维基百科

在面向对象的编程中,虚函数或虚方法是一种函数或方法,其行为可以通过具有相同签名的函数在继承类中重写.

但是我可以在不使用virtual关键字的情况下覆盖如下所示的方法

#include <iostream>

using namespace std;

class A {
    public:
        int a();
};

int A::a() {
    return 1;   
}

class B : A { 
    public:
        int a();
};

int B::a() {
    return 2;
}

int main() {
    B b;
    cout << b.a() << endl;
    return 0;
}

//output: 2
Run Code Online (Sandbox Code Playgroud)

如下所示,函数A :: a被成功覆盖了B :: a而不需要 virtual

令我困惑的是这个关于虚拟析构函数的陈述,也来自维基百科

如下例所示,对于C++基类来说,拥有一个虚拟析构函数以确保始终调用最派生类的析构函数非常重要.

那么virtual还告诉编译器调用父代的析构函数?这似乎与我原来的理解virtual"使功能可以覆盖" 非常不同

Con*_*tah 16

进行以下更改,您将看到原因:

#include <iostream>

using namespace std;

class A {
    public:
        int a();
};

int A::a() {
    return 1;   
}

class B : public A { // Notice public added here
    public:
        int a();
};

int B::a() {
    return 2;
}

int main() {
    A* b = new B(); // Notice we are using a base class pointer here
    cout << b->a() << endl; // This will print 1 instead of 2
    delete b; // Added delete to free b
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

现在,让它像你想象的那样工作:

#include <iostream>

using namespace std;

class A {
    public:
        virtual int a(); // Notice virtual added here
};

int A::a() {
    return 1;   
}

class B : public A { // Notice public added here
    public:
        virtual int a(); // Notice virtual added here, but not necessary in C++
};

int B::a() {
    return 2;
}

int main() {
    A* b = new B(); // Notice we are using a base class pointer here
    cout << b->a() << endl; // This will print 2 as intended
    delete b; // Added delete to free b
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

你在虚拟析构函数中包含的注释是完全正确的.在你的样本中没有什么需要清理,但是说A和B都有析构函数.如果它们没有标记为虚拟,那么将使用基类指针调用哪一个?提示:当它没有标记为虚拟时,它将与a()方法完全相同.

  • 无需使用new/delete复杂化示例:`B obj; A*p =&obj;`或'A&ref = obj;` (2认同)

bma*_*ies 9

您可以将其想象如下.

Java中的所有函数都是虚拟的.如果您有一个带有函数的类,并且您在派生类中重写该函数,则无论您用于调用它的变量的声明类型,都将调用它.

另一方面,在C++中,它不一定会被调用.

如果你有一个基类Base和派生类Derived,并且它们都有一个名为'foo'的非虚函数,那么

Base * base;
Derived *derived;

base->foo(); // calls Base::foo
derived->foo(); // calls Derived::foo
Run Code Online (Sandbox Code Playgroud)

如果foo是虚拟的,那么两者都调用Derived :: foo.