覆盖非虚方法

24 浏览
0 Comments

覆盖非虚方法

假设在Visual C++ 2010中有以下情景:

#include 
#include 
using namespace std;
class Base
{
public:
    int b;
    void Display()
    {
        cout << "Base: Non-virtual display." << endl;
    };
    virtual void vDisplay()
    {
        cout << "Base: Virtual display." << endl;
    };
};
class Derived : public Base
{
public:
    int d;
    void Display()
    {
        cout << "Derived: Non-virtual display." << endl;
    };
    virtual void vDisplay()
    {
        cout << "Derived: Virtual display." << endl;
    };
};
int main()
{
    Base ba;
    Derived de;
    ba.Display();
    ba.vDisplay();
    de.Display();
    de.vDisplay();
    _getch();
    return 0;
};

理论上,这个小应用程序的输出应该是:

Base: Non-virtual display.

Base: Virtual display.

Base: Non-virtual display.

Derived: Virtual display.

因为Base类的Display方法不是一个virtual方法,所以Derived类不应该能够覆盖它。对吗?

问题是,当我运行这个应用程序时,它打印出这个:

Base: Non-virtual display.

Base: Virtual display.

Derived: Non-virtual display.

Derived: Virtual display.

所以要么我不理解virtual方法的概念,要么在Visual C++中发生了一些奇怪的事情。

这是怎么回事?

0
0 Comments

在C++中,如果派生类中存在与基类同名的方法,那么派生类中的方法会隐藏基类中的方法。如果这不是这样的话,那么尝试创建与基类非虚方法同名的方法应该会报错。实际上,这是允许的,并且没有问题。如果直接调用方法,那么会正常调用该方法。

然而,由于非虚函数的特性,C++的方法查找机制不会使用多态性。例如,如果你创建了一个派生类的实例,但是通过基类的指针调用了你的"Display"方法,那么基类的方法会被调用;而对于"vDisplay",派生类的方法会被调用。

下面是一个示例代码:

Base *b = &ba;
b->Display();
b->vDisplay();
b = &de;
b->Display();
b->vDisplay();

输出结果如下:

Base: Non-virtual display.
Base: Virtual display.
Base: Non-virtual display.
Derived: Virtual display.

在这个例子中,通过基类指针调用方法时,非虚方法会调用基类的方法,而虚方法会调用派生类的方法。

此外,你也可以使用作用域解析语法从派生类实例中调用(非虚)基类方法。

因此,可以肯定地说,无论是否将方法声明为虚方法,都可以在基类中定义一个方法,并在派生类中重写它。唯一的区别是,如果基类指针指向派生类对象,那么如果该方法不是虚方法,将调用基类的方法;如果该方法是虚方法,将调用派生类的方法。没有其他区别。

关于是否仅需更改头文件,还是必须使用"virtual"关键字重新编译源文件的问题,"virtual"关键字只允许在类声明本身之外的定义中使用。因此,不需要将其添加到cpp文件中。但是,你需要重新编译代码。

0
0 Comments

在C++中,为了实现运行时多态性,需要重写虚函数。虚函数是一种在基类中声明的函数,可以在派生类中进行重写。重写虚函数允许在运行时根据实际对象类型调用相应的函数。

在上述代码中,给出了三种不同类型的函数:纯虚函数、虚函数和普通函数。纯虚函数是在基类中声明的,并且需要在派生类中进行重写。纯虚函数的声明方式为virtual void fun1() = 0,其中的"= 0"表示该函数是纯虚函数,必须在派生类中进行重写。

虚函数是在基类中声明的函数,可以在派生类中进行重写。虚函数的声明方式为virtual void fun2()。派生类中可以重写虚函数来提供特定的实现。

普通函数是在基类中声明的函数,不需要在派生类中进行重写。普通函数的声明方式为void fun3()。普通函数在派生类中不需要进行重写,因为它们不具有多态性。

因此,如果想要实现运行时多态性,需要在派生类中重写虚函数。如果重写了非虚函数或者纯虚函数,将会导致错误。

0
0 Comments

在C++中,默认情况下,非虚方法在编译时绑定到调用者。这意味着在运行时,无法知道实际指向的对象是什么。因此,只有变量的类型才是重要的,即“Base”。

这种情况下,方法的重写将导致无法实现多态性,因为在编译时已经确定了方法的调用者。如果我们尝试在派生类中重写非虚方法,实际上只是在创建一个新的方法,而不是重写基类的方法。

为了解决这个问题,我们需要将基类的方法声明为虚方法。虚方法允许在派生类中重新定义,并且在运行时选择正确的方法来调用。这样,我们就可以实现多态性,并在运行时确定实际指向的对象。

要将方法声明为虚方法,我们只需要在基类的方法声明前添加关键字“virtual”。例如:

class Base {

public:

virtual void method() {

// 基类的方法实现

}

};

class Derived : public Base {

public:

void method() override {

// 派生类的方法实现

}

};

通过将基类的方法声明为虚方法,并在派生类中重新定义该方法,我们可以实现正确的方法调用并实现多态性。这样,无论指针指向的对象是基类还是派生类,都可以正确地调用适当的方法。

0