虚拟虚空有什么作用?

时间:2019-04-04 21:31:48

标签: c++ virtual-functions

我想问为什么打印出A? virtual void是做什么的? Class B: public A还能做什么?我不太了解这是怎么回事。

#include <iostream>

class A
{
    public: virtual void f() {std::cout << "A";}
};
class B : public A
{
    public: void f() {std::cout << "B ";}
}; 

int main()
{
    A* aPtr {new B() };
    aPtr ->f();
}

2 个答案:

答案 0 :(得分:1)

  

虚拟虚空有什么作用?

number是一个关键字。作为函数说明符,它指定成员函数是虚拟的。虚拟成员函数支持动态调度。

virtual也是一个关键字。这是一种特殊类型,作为函数的返回类型,意味着该函数不返回值。


  

我想问为什么打印出A?

不是。它打印出B。这样做是由于动态调度。函数调用将分派到最派生的重写,在这种情况下为void

  

B类也做什么:公共A做

(如果将B::f固定为关键字Class),它将声明类class是正在定义的类A的公共基类

派生类继承其基类的功能,并且其实例包含一个基类子对象。

答案 1 :(得分:1)

将virtual放在类的成员函数之前,使您可以在派生类中“覆盖”它(从原始类继承的类...例如,在您的示例中,B是派生类)。当然,所有这些都涉及继承,这在大多数面向对象的语言中都是一个巨大的话题。

通常,如果我们知道要在派生类中重新定义该函数(并且很有可能会做一些不同的事情),则可以在成员函数前面使用virtual关键字。例如,考虑以下

class Robot {
    public:
        virtual void talk() {
           cout << "I'm a generic robot" << endl;
        }
    private:
        bool rusty;
};

class SmartRobot: Robot {
    public:
        void talk() {
           cout << "Hiyah I'm a smart robot and I get good grades (if I go to school)" << endl;
        }
};

现在,如果我们构造一个SmartRobot对象(例如您如何构造B对象),则由于Robot中的talk()函数是虚拟的,因此编译器将知道将调用SmartRobot类中的talk()版本(始终称为派生程度最高的版本)。但是,如果我们在Robot类中的talk前面删除了virtual关键字,则编译器将调用Robot类中定义的talk()函数,这可能不是我们想要的!

要回答第二个问题,类B:public A表示B源自A,也就是A的子类。您可以将其视为“ B IS-A种A”,就像上面的示例一样,“ SmartRobot IS是一种机器人”,这意味着B可以访问A中的公共成员和受保护成员,但不能访问任何私有成员。因此,SmartRobot可以调用Robot中的talk()函数,但不能访问Robot中的生锈成员变量。

最后,在您的示例中(假设void和f之间有一个空格),输出应该为B,因为f()在A中是虚拟的,并且B派生自A