具有虚函数的对象的堆栈分配导致意外行为(调用基 class 方法而不是子 class 方法)
Stack allocation of object with virtual function leads to unexpeted behavior (calls base class method instead of child class)
我有一个基本的 class 被继承的 class 玩家继承。
class Entity{
public:
virtual std::string getName(){ return "Hello World";}
};
在我的扩展 class 中,我只是想重写 getName 方法,就像下面的片段:
class Player : public Entity{
public:
std::string getName() override { return "Hello from Player"; }
};
当我在堆上分配对象时,它调用正确的扩展 class 方法,我得到输出 "Hello from Player" 堆上的分配对象是这样完成的:
Entity* e= new Entity;
Player* p = new Player;
Entity* entity = p;
std::cout << entity->getName() <<std::endl;
但是当我在堆栈上分配相同的对象时,它调用基方法而不是重写方法,我已经完成堆栈分配:
Entity e1;
Player p1;
Entity entity1 = p1;
std::cout << entity1.getName() <<std::endl;
整个代码的组合输出如下所示:
Hello from Player
-------------- Hello World
我正在使用带有 c++11 标志的 clang 版本 7.0.0-3~ubuntu0.18.04.1,希望有人能向我解释这种行为。堆栈或堆分配不应该对对象的行为方式没有影响吗?还是我错过了什么?
我已经尝试 google 这个主题,但没有得到任何准确的相关答案。
这是一个 repl.it link: https://repl.it/repls/GleefulDroopyRay
叫做切片。
当你这样做时:
Entity entity1 = p1;
您调用 class 实体的复制构造函数并创建一个作为基础的实际实体对象。于是调用了base的方法
如果您想要一个对象在堆栈上的示例,您可以执行以下操作之一:
Player p1;
Entity& entity1 = p1;
std::cout << entity1.getName() <<std::endl;
或
Player p1;
Entity* pEntity = &p1;
std::cout << pEntity->getName() <<std::endl;
我有一个基本的 class 被继承的 class 玩家继承。
class Entity{
public:
virtual std::string getName(){ return "Hello World";}
};
在我的扩展 class 中,我只是想重写 getName 方法,就像下面的片段:
class Player : public Entity{
public:
std::string getName() override { return "Hello from Player"; }
};
当我在堆上分配对象时,它调用正确的扩展 class 方法,我得到输出 "Hello from Player" 堆上的分配对象是这样完成的:
Entity* e= new Entity;
Player* p = new Player;
Entity* entity = p;
std::cout << entity->getName() <<std::endl;
但是当我在堆栈上分配相同的对象时,它调用基方法而不是重写方法,我已经完成堆栈分配:
Entity e1;
Player p1;
Entity entity1 = p1;
std::cout << entity1.getName() <<std::endl;
整个代码的组合输出如下所示:
Hello from Player -------------- Hello World
我正在使用带有 c++11 标志的 clang 版本 7.0.0-3~ubuntu0.18.04.1,希望有人能向我解释这种行为。堆栈或堆分配不应该对对象的行为方式没有影响吗?还是我错过了什么? 我已经尝试 google 这个主题,但没有得到任何准确的相关答案。 这是一个 repl.it link: https://repl.it/repls/GleefulDroopyRay
叫做切片。
当你这样做时:
Entity entity1 = p1;
您调用 class 实体的复制构造函数并创建一个作为基础的实际实体对象。于是调用了base的方法
如果您想要一个对象在堆栈上的示例,您可以执行以下操作之一:
Player p1;
Entity& entity1 = p1;
std::cout << entity1.getName() <<std::endl;
或
Player p1;
Entity* pEntity = &p1;
std::cout << pEntity->getName() <<std::endl;