C++中引用和接口指针的行为不同

3

我试图编写一个变量值接口。基类只提供了一个枚举字段,存储变量的类型(如intchar等),以及一些虚拟函数。 继承此接口的类应该实现每个变量类型的表示。

#include <iostream>

enum Type
{
    INT, CHAR
};

class Var
{
    Type type;
public:
    Var(Type t):
        type(t)
    {}
    virtual void printValue()
    {
        std::cout << "-\n";
    }
    virtual void printType()
    {
        std::cout << type << std::endl;
    }
};

class IntVar : public Var
{
    int value;
public:
    IntVar(int i):
        Var(INT),
        value(i)
    {}
    void printValue()
    {
        std::cout << value << std::endl;
    }
};

class CharVar : public Var
{
    char value;
public:
    CharVar(char c):
        Var(CHAR),
        value(c)
    {}
    void printValue()
    {
        std::cout << value << std::endl;
    }
};

然后我尝试了这个:

Var* np = new IntVar(1);

np->printType();
np->printValue();
np = new CharVar('a');
np->printType();
np->printValue();

输出结果为

0(类型:INT)、1、1(类型:CHAR)、a

所以一切都按预期工作,但是当我尝试使用引用重复相同的操作时,结果有些奇怪。

Var& nr = *(new IntVar(1));
nr.printType();
nr.printValue();
nr = *(new CharVar('a'));
nr.printType();
nr.printValue();

这里的输出是

0(Type :: INT),1,1(Type :: CHAR)和1

为什么使用指针时代码可以运行,而使用引用时却无法运行?还是我忽略了一些明显的错误?


你错误地使用了 new。你的程序存在内存泄漏。 - celticminstrel
3个回答

4
使用指针的解决方案首先使nr指向一个IntVar,然后指向一个CharVar
使用引用的解决方案创建一个IntVar对象,然后为该对象创建一个新名称(nr),然后根据CharVar的值更改此对象的值。
与指针不同,引用不能像您所做的那样重新定位。引用在其生命周期内引用同一对象。

1

该语句

nr = *(new CharVar('a'));

这是一个具有非常不同含义的赋值,与

np = new CharVar('a');

第12.8节:

非联合类X的隐式定义的复制/移动赋值运算符执行其子对象的逐成员复制/移动赋值。首先按照它们在基础说明符列表中声明的顺序分配X的直接基类,然后按照它们在类定义中声明的顺序分配X的直接非静态数据成员...

nr使用从Var复制字段的隐式赋值运算符Var :: operator =()。您没有更改引用类型,它仍然是对IntVar对象的引用。


1
Var& nr = *(new IntVar(1));  //nr are Bound to IntVar object
nr=*(new CharVar('a'));    //replace the base part of IntVar object
                            //  by the base part of CharVar object

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接