引用变量和继承

时间:2011-11-22 10:23:19

标签: c++ reference vptr

以下代码:

#include <stdio.h>
class Parent
{
public:
    virtual void func() {printf("Parent\n");}
};

class Child1 : public Parent
{
    virtual void func() {printf("Child1\n");}
};

class Child2 : public Parent
{
    virtual void func() {printf("Child2\n");}
};

int main(int argc, char* argv[])
{
    Parent & obj = Child1();
    obj.func();
    obj = Child2();
    obj.func();
    return 0;
}

产生以下结果:

expected: Child1 Child2.

actual: Child1 Child1. 

(在VS2010上编译)

我猜vptr不会被赋值改变。它有一种方法可以重新创建它(除了使用指向Parent的指针并使用new分配它)?

感谢

5 个答案:

答案 0 :(得分:3)

您正在调用obj上的默认赋值运算符,该运算符仍然是Child1类型,其参数类型为Child2。对象本身仍然是Child1类型。您可以通过在所有3个类上实现operator =并在那里插入print语句来验证这一点。

答案 1 :(得分:1)

无法重新引用引用 - 它们在整个生命周期中引用相同的对象。如果你想要一些可以改变它引用的对象的东西,那么你需要使用[智能]指针而不是引用。

您在此处执行的操作是slicing Child2的实例,方法是将其分配给Child1的实例。

答案 2 :(得分:1)

Parent & obj = Child1();

您创建对Child1类型对象的引用。这就像说

Child1 c1;
Parent& obj = c1;

obj现在只是c1的另一个名称,它是Child1类型的对象。

obj = Child2();
obj.func();

现在,这就像说

c1 = Child2();
c1.func();

所以你看,你仍然在func类型的对象上调用Child1

答案 3 :(得分:1)

C ++中的两个基本属性:一个对象,一旦创建,永远不会 更改其类型,引用一旦初始化,始终引用 同一个对象。

这里发生的是你正在调用提供的编译器 operator=的非虚拟Parent,几乎肯定不是什么 你自找的。但更一般地说,赋值和继承不是 一起工作(正是因为你不能改变一个类型 宾语);大多数时候,在使用继承时,你应该禁止 赋值(例如,从boost::noncopyable继承)。它的 可以使用。实现多态类的值语义 字母/信封成语,但这是一个沉重的解决方案,很少 适当。

(我可能会补充一点,你的代码不能用C ++编译器编译。你是 使用临时初始化对非const的引用,而不是 合法的C ++。允许这是Microsoft扩展。)

答案 4 :(得分:0)

您正在做的事情应该在编译时出错。您不能将临时变量(由Child2()创建)分配给引用变量。您必须在Child2之前创建一个实例,并将该变量分配给崇敬者。