我想问为什么打印出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();
}
答案 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