对C++的虚拟函数感到困惑
Confused about Virtual Functions C++
我是一个c++n00b,我不确定我是否找对了地方,但我对此感到困惑:
include <iostream>
using namespace std;
class Enemy
{
public:
void sayHere()
{
cout<<"Here"<<endl;
}
virtual void attack()
{
}
};
class Monster: public Enemy
{
public:
virtual void attack()
{
cout<<"RAWR"<<endl;
}
};
class Ninja: public Enemy
{
public:
virtual void attack()
{
cout<<"Hiya!"<<endl;
}
};
int main()
{
Ninja n;
Monster m;
Enemy enemies[2];
enemies[0] = m;
enemies[1] = n;
for(int i = 0; i<2; i++)
{
enemies[i].sayHere();
enemies[i].attack();//Will not be overriden
}
return 0;
}
我的问题是为什么Monster或Ninja类中的attack((函数没有被覆盖?任何帮助,哪怕是一个链接,都将不胜感激。
只需执行:
Enemy* n = new Ninja();
Enemy* m = new Monster();
n->sayHere();
n->attack();
m->sayHere();
m->attack();
delete n;
delete m;
你想怎么做就怎么做。你需要使用指针来使它工作。原因在于动态绑定的工作方式。
每当程序声明了C++虚拟函数时,就会为该类构造一个v表。v表由指向类的虚拟函数的地址和指向派生类的每个对象的函数的指针组成。每当对c++虚拟函数进行函数调用时,都会使用v-table来解析函数地址。这就是在虚拟函数调用期间动态绑定的发生方式。
其思想是,编译器根据对象的内存地址存储指向每个方法的指针。它需要指针来访问表并调用相应的函数指针。想一想,如果你想编写一个面向对象的C版本,你将如何提供继承和多态性这样的机制?当你这样想的时候,这是有道理的。
我刚刚读到你要离开JAVA。在JAVA中,大多数对象都存储在堆中。这一切都只是暗示。
JAVA的
Enemy n = new Ninja();
n.attack();
大致相当于
Enemy* n = new Ninja();
n->attack();
在哪里。JAVA中的运算符更像c++中的->运算符。在这两种情况下,n都在堆上。Java只是对您隐藏了所有指针和内存管理的东西。这就是为什么您可能对JAVA和C#中动态绑定的工作方式一无所知。
这与你不能通过指针访问敌人有关:
Ninja n;
Monster m;
Enemy *enemies[2];
enemies[0] = &m;
enemies[1] = &n;
for (int i = 0; i < 2; i++)
{
enemies[i]->sayHere();
enemies[i]->attack();
}
return 0;
除非通过指针或引用访问对象,否则虚拟函数调用将无法工作。为了让它发挥作用,你需要将你的敌人阵列重写为
Enemy *enemies[2];
enemies[0] = &m;
enemies[1] = &n;
请注意,您必须将所有enemies[i].
更改为enemies[i]->
。
Enemy enemies[2];
enemies[0] = m;
enemies[1] = n;
这只是对象切片——只会复制派生对象中的Enemy
对象。虚拟功能无法发挥作用。
这种现象称为对象切片。
相关文章:
- "error: no matching function for call to"构造函数错误
- 什么时候调用组成单元对象的析构函数
- 继承函数的重载解析
- 为什么随机数生成器不在void函数中随机化数字,而在main函数中随机化
- C++模板来检查友元函数的存在
- 递归函数计算序列中的平方和(并输出过程)
- 对RValue对象调用的LValue ref限定成员函数
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 在C++STL中是否有Polyval(Matlab函数)等价物?
- 为什么使用 "this" 指针调用派生成员函数?
- 将对象数组的引用传递给函数
- 函数调用中参数的顺序重要吗
- 函数向量_指针有不同的原型,我可以构建一个吗
- 使用不带参数的函数访问结构元素
- 代码在main()中运行,但在函数中出现错误
- 内置函数可查看CPP中的成员变量
- 如何获取std::result_of函数的返回类型
- 如何在c++中为模板函数实例创建快捷方式
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗