2

我有两个吸气剂成员:

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 源获取我的值又有什么关系呢?

4

5 回答 5

14

您不是在尝试进行非常量到 const 的转换。您正在尝试调用两个不是 const 和 const 引用的方法(调用 prev 和 value)。const 语义严格禁止这种类型的操作。

您可以做的是直接使用字段 prev_ 和 value_ 。因为它是同一类型的成员,所以您可以访问将在 const 对象上可用的 privates。

于 2009-07-31T16:07:54.997 回答
3

我认为 C++ 允许在函数参数中进行非 const 到 const 的转换,例如:

你正试图做完全相反的事情:从常量到非常量。调用非 const 成员函数,编译器将绑定表达式(这是用于绑定指针的 aNode const到 a )。因此它将删除 const - 不允许,因为它会在 const 对象上调用非常量函数。Node&this

/* 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
}
于 2009-07-31T16:12:12.570 回答
2

你是对的 - const 意味着你承诺不会改变任何东西。编译器通过不允许您调用该对象上的方法来让您信守诺言,这些方法本身并不承诺不会更改任何内容。

于 2009-07-31T16:09:27.240 回答
2

在构造函数的声明中声明了Node(Node const& other)参数。这意味着您只能在其上调用方法。otherconstconst

您正在从构造函数调用other.prev()and other.value(),它们都是非const方法,因此编译器会抱怨。

于 2009-07-31T16:17:30.533 回答
2

正如其他人所提到的,您在编译器不允许的 const 对象上调用非常量方法。

一个简单的解决方法是将你的 getter 函数标记为 const:

Node* prev() const { return prev_; }
int value()  const { return value_; }

因为他们不修改对象;现在可以使用 const 对象调用它们。事实上,无论如何都应该这样做,以便该类的用户可以使用 const 对象调用这些 getter。

但是,如果您的复制 ctor 看起来像这样,您还有另一个潜在的问题:

Node(Node const& other) : prev_(other.prev()), value_(other.value()) { }

副本和原件都将指向其prev_成员中的同一个 Node 对象。根据类语义,这可能没问题,但可能是所有权问题或其他逻辑不一致。

于 2009-07-31T16:54:12.923 回答