我有两个吸气成员:
Node* prev() { return prev_; }
int value() { return value_ }
请注意缺少const标识符(我忘了它们,但现在我想知道为什么这不起作用)。我想把它编译成:
Node(Node const& other) : prev_(other.prev()), value_(other.value()) { }
编译器拒绝此操作。我认为C ++允许在函数参数中进行非const到const转换,例如:
{
Foo(int bar);
}
Foo(const int bar)
{
//lala
}
为什么它不能让我用复制构造函数做同样的事情? const标识符意味着我保证不会改变任何东西,那么为什么从const或非const源获取我的值会有什么影响呢?
答案 0 :(得分:14)
您不是要尝试进行非const到const的转换。您试图调用两个不是const的const方法(调用prev和value)。 const语义严格禁止这种类型的操作。
您可以做的是直接使用字段prev_和value_。因为它是相同类型的成员,所以您可以访问const对象上可用的私有。
答案 1 :(得分:3)
我认为C ++允许在函数参数中进行非const到const转换,例如:
你正试图做相反的事情:Const到非const。调用非const成员函数时,编译器会将表达式(Node const
绑定到Node&
以绑定this
指针)。因此它将删除const - 不允许,因为它会在const对象上调用非const函数。
/* class Foo */ {
Foo(int bar);
}
/* Foo:: */ Foo(const int bar)
{
//lala
}
那个代码完全是另一回事。它声明了一个函数(构造函数)两次,唯一的区别是一次参数是const,另一次不是。两次函数的类型都是相同的,因此它们不会发生冲突(const
参数只会在函数体内产生影响 - 它不会对调用者产生任何影响)。此外,此代码不包含任何调用(假设第一个块在某个函数内)。
如果您想知道:如果以上两个版本相同 - 为什么不是以下?那么这是因为下面包含另一个间接层:下面,引用本身(顶层)不是const(你不能直接将const
放在引用本身上) ,但引用的类型是const。此时,在确定函数类型时,const 不被忽略。
/* class Foo */ {
Foo(int &bar);
}
// different thing, won't work!
/* Foo:: */ Foo(const int &bar)
{
//lala
}
答案 2 :(得分:2)
你是对的 - const意味着你保证不会改变任何东西。编译器通过不允许您调用该对象上的方法来保证您的承诺,这些方法本身不会保证不会更改任何内容。
答案 3 :(得分:2)
在构造函数Node(Node const& other)
的声明中,参数other
被声明为const
。这意味着您只能在其上调用const
方法。
您正在从构造函数中调用other.prev()
和other.value()
这两个方法都是非const
方法,因此编译器会抱怨。
答案 4 :(得分:2)
正如其他人所提到的,你在const对象上调用非const方法,编译器不允许这样做。
一个简单的解决方法就是将你的getter函数标记为const:
Node* prev() const { return prev_; }
int value() const { return value_; }
因为他们不修改对象;现在可以使用const对象调用它们。实际上,无论如何都应该这样做,以便类的用户可以使用const对象调用这些getter。
但是,如果您的副本看起来像:
,那么您还有另一个潜在的问题Node(Node const& other) : prev_(other.prev()), value_(other.value()) { }
副本和原始文件都将指向其prev_
成员中的同一个Node对象。根据类语义,这可能没问题,但可能是所有权问题或其他逻辑不一致。