C ++:如何处理需要修改的const对象?

时间:2009-10-15 14:04:17

标签: c++ casting const

我在代码中占有一席之地

const myType & myVar = someMethod();

问题在于:

  • someMethod()返回const myType

  • 我需要稍后更改myVar,方法是在对象处于无效状态时指定默认值。所以我需要让myVar成为非const。

    1. 我认为我需要让myVar成为非参考,对吧?例如。 myType myVar

    2. 这种const-to-nonconst的C ++“正确”方法是什么?静态演员?词汇演员?还有别的吗?

我可以访问boost的词汇演员,所以我不介意这个选项,但我更喜欢非 boost 解决方案,如果它最终我不允许使用 boost

谢谢!

7 个答案:

答案 0 :(得分:9)

你可能不需要任何演员。如果您可以复制T,那么您还可以复制T const,排除病理情况。 T const的副本不必是T const本身。

myType myVar = someMethod(); // Creates a non-const copy that you may change.

答案 1 :(得分:5)

我不会使用const_cast解决方案,复制对象可能无效。相反,为什么不有条件地分配给另一个const引用呢?如果myVar有效,请指定。如果不是,请指定默认值。然后下面的代码可以使用这个新的const引用。一种方法是使用条件表达式:

const myType& myOtherVar = (myVar.isValid() ? myVar : defaultVar);

另一种方法是编写一个带有const引用(myVar)的函数,并返回myVar或defaultVar,具体取决于myVar的有效性,并将其返回值赋给myOtherVar。

第三种方法是使用const指针,将其指向myVar的地址或默认对象的地址。

答案 2 :(得分:1)

const_cast<type without const>()

但是,someMethod()真的会返回const myType吗?如果是这样,你正在引用一个临时的 - 它将被销毁,你的参考将是坏的。将myVar更改为非ref(因此它会复制) - 在这种情况下无需将其声明为const。或者,如果someMethod()返回引用,请使用const_cast(如果必须)(但您正在更改someMethod认为不会更改的内容。)

答案 3 :(得分:1)

没有“C ++”方式(不仅是这种方式,还包括任何方式)。

糟糕的方法是使用const_cast,但行为将是未定义的(读取:不要这样做)。

您应该做的是复制对象,然后修改副本。它是处理不可变对象的唯一正确的方法。

答案 4 :(得分:0)

尝试以下

myType& mutableMyVar = const_cast<myType&>(myVar);

一般来说,删除const是一个坏主意。调用方法返回一个对它认为将被视为const的变量的引用。如果通过删除const并修改变量来违反此假设,则可以将任一对象置于有效状态。

在您的特定情况下,这可能是合法的,但一般来说这是应该避免的事情

答案 5 :(得分:0)

您可以使用复制构造函数或某些赋值运算符从const对象创建对象,然后对其进行修改。

但我认为你最好先看看为什么函数首先返回const类型。将它声明为const是有原因的。如果您非常确定这是您想要的,那么您可以像这样const_cast远离const:

T obj1 = const_cast<T&> (obj); 

答案 6 :(得分:0)

  

执行此const-to-nonconst的C ++“正确”方法是什么?静态演员?词汇演员?还有别的吗?

没有C ++方式。由于某种原因,该类的作者决定您不能通过此方法修改实例。

如果您是作者,则可以使其返回非const引用。但是那些仍然是可疑的,除非这个类真的没有业务隐藏它(例如,矢量不会隐藏它为你拥有的,只是隐藏如何它为你拿东西。)

一种更好的方法(取决于它的全部内容)也可能不会暴露成员进行外部操作,而是提供一种方法来为您执行此操作。例如:

class BadPosition
{
    int x, y;
 public:
    int& get_x() { return x; }
    int& get_y() { return x; }
    //...
};

BadPosition p;
p.get_x() += 1;
p.get_y() += -1;

class BetterPosition
{
    int x, y;
 public:
    void move(int x_inc, int y_inc) { x += x_inc; y += y_inc; }
    //...
};

BetterPosition p;
p.move(1, -1);

如果您以后需要将该类置于有效状态,那么可以考虑使其构造函数执行此操作。如果你不能这样做,至少提供一个Init()方法,以免使这样一个复杂的类完全依赖外部操作成可用的东西。

当然可能有其他方式不需要强制转换,例如,您可以创建副本,修改它,然后使用修改后的副本将整个实例替换为另一个(假设这足以构建它):< / p>

X x;
...
Y y = x.get();
y.modify();
x = X(y);

编辑:那么该类按值返回?在这种情况下,应该没有办法修改类中的实例,因为你得到的只是一个副本。您可以使用const引用引用它,但即使您从该引用中删除constness,您仍然引用临时引用。

我上面的回复假设它返回了一个const引用,因为这似乎是一个更明智的事情(我没有看到人们经常返回 const 值,尽管可能有强烈的人推荐它。)