ano*_*ous 39 c++ virtual overriding function
在函数前使用虚拟词virtual的目的是什么?如果我想让子类覆盖父函数,我只需声明相同的函数,如void draw(){}
.
class Parent {
public:
void say() {
std::cout << "1";
}
};
class Child : public Parent {
public:
void say()
{
std::cout << "2";
}
};
int main()
{
Child* a = new Child();
a->say();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出为2.
那么,为什么保留字virtual
在标题中是必要的say()
呢?
谢谢一堆.
Don*_*nie 37
如果函数是虚函数,那么你可以这样做并仍然得到输出"2":
Parent* a = new Child();
a->say();
Run Code Online (Sandbox Code Playgroud)
这是因为virtual
函数使用实际类型,而非虚函数使用声明的类型.阅读多态性,以便更好地讨论您为什么要这样做.
Jer*_*fin 26
尝试使用:
Parent *a = new Child();
Parent *b = new Parent();
a->say();
b->say();
Run Code Online (Sandbox Code Playgroud)
没有virtual
,两者都打印'1'.添加虚拟,孩子将像孩子一样,即使它通过指向一个指针被引用Parent
.
kro*_*lth 18
这是我认为多态如何工作的经典问题.主要思想是您要抽象每个对象的特定类型.换句话说:你希望能够在不知道它是孩子的情况下调用Child实例!
下面是一个示例:假设您有类"Child"和类"Child2"和"Child3",您希望能够通过它们的基类(Parent)引用它们.
Parent* parents[3];
parents[0] = new Child();
parents[1] = new Child2();
parents[2] = new Child3();
for (int i=0; i<3; ++i)
parents[i]->say();
Run Code Online (Sandbox Code Playgroud)
你可以想象,这是非常强大的.它允许您根据需要多次扩展Parent,并且使用Parent指针的函数仍然可以工作.为了使其像其他人一样提及,您需要将该方法声明为虚拟方法.
Dav*_*eas 16
如果不使用virtual
关键字,则不要覆盖,但rahter在派生类中定义一个隐藏基类方法的无关方法.也就是说,没有virtual
,Base::say
并且Derived::say
是无关的 - 这就是名称巧合.
当您使用虚拟关键字(在基础中需要,在派生类中是可选的)时,您告诉编译器从该基础派生的类将能够覆盖该方法.在这种情况下,Base::say
和Derived::say
被认为是相同的方法的替代.
当您使用引用或指向基类的指针来调用虚方法时,编译器将添加适当的代码,以便调用最终的覆盖(在大多数派生类中的覆盖,它定义具体实例的层次结构中的方法)正在使用).请注意,如果不使用引用/指针而是使用局部变量,则编译器可以解析调用,并且不需要使用虚拟调度机制.
jok*_*oon 12
我亲自测试了它,因为我们可以考虑很多事情:
#include <iostream>
using namespace std;
class A
{
public:
virtual void v() { cout << "A virtual" << endl; }
void f() { cout << "A plain" << endl; }
};
class B : public A
{
public:
virtual void v() { cout << "B virtual" << endl; }
void f() { cout << "B plain" << endl; }
};
class C : public B
{
public:
virtual void v() { cout << "C virtual" << endl; }
void f() { cout << "C plain" << endl; }
};
int main()
{
A * a = new C;
a->f();
a->v();
((B*)a)->f();
((B*)a)->v();
}
Run Code Online (Sandbox Code Playgroud)
输出:
A plain
C virtual
B plain
C virtual
Run Code Online (Sandbox Code Playgroud)
我认为一个好的,简单的和简短的答案可能看起来像这样(因为我认为能够理解更多的人可以记住更少,因此需要简短而简单的解释):
虚方法检查指针指向的实例的DATA,而经典方法因此不调用与指定类型相对应的方法.
该功能的要点如下:假设您有一个A的数组.该数组可以包含B,C,(甚至派生类型).如果要按顺序调用所有这些实例的相同方法,则应调用每个重载的方法.
我发现这很难理解,显然任何C++课程都应该解释如何实现这一点,因为大多数时候你刚刚学过虚函数,你使用它们,但直到你理解编译器如何理解它们以及如何执行它们会处理电话,你是在黑暗中.
关于VFtables的事情是我从来没有解释过它添加了什么样的代码,而且显然这里C++需要比C更多的经验,这可能是C++在早期被标记为"慢"的主要原因:事实上,它很强大,但就像所有东西一样,如果你知道如何使用它会很强大,或者你只是"把你的整条腿吹走".