【问题标题】:Cryptic error message when passing const parameters as arguments将 const 参数作为参数传递时的神秘错误消息
【发布时间】:2013-10-17 10:03:28
【问题描述】:

所以我正在编写一个双向链表的实现。这是实现单个节点的类的构造函数:

DNode::DNode(const int a_key, const DNode* a_prev, const DNode* a_next) 
    : key(a_key), prev(a_prev), next(a_next) {}

我之所以写const int a_key, const DNode* a_prev, const DNode* a_next是因为构造函数没有理由修改它们。所以我只是想保护自己免于在构造函数中进行任何不需要的修改。这是好事吗?

编译输出如下错误:

dnode.cpp:6:89: 错误:无法初始化类型的成员子对象 'DNode *' 的左值类型为 'const DNode *' DNode::DNode( const int a_key, const DNode* a_prev, const DNode* a_next) : key(a_key), 上一个(a_prev),下一个(a_next){}

dnode.cpp:6:103:错误:无法初始化成员 'DNode *' 类型的子对象,左值类型为 'const DNode *' DNode::DNode(const int a_key, const DNode* a_prev, const DNode* a_next ) : key(a_key), prev(a_prev), next(a_next) {}

我不明白错误信息。 DNode* 是指针类型,而不是左值。欢迎任何帮助。

=== 编辑 ===

我将我的代码修改为以下内容。

dnode.h

class DNode {

 public:

  //
  DNode( const int a_key, const DNode& a_prev, const DNode& a_next );

  //
  int get_key() const;
  DNode* get_prev() const;
  DNode* get_next() const;

  //
  void set_key( const int a_key );
  void set_prev( const DNode& a_prev );
  void set_next( const DNode& a_next );

  //
 private:

  int key;
  DNode* prev;
  DNode* next;

};

dnode.cpp

//
DNode::DNode( const int a_key, const DNode& a_prev, const DNode& a_next ) 
: key(a_key), prev(&a_prev), next(&a_next) {}

//
int DNode::get_key() const { return key; }
DNode* DNode::get_prev() const { return prev; }
DNode* DNode::get_next() const { return next; }

//
void DNode::set_key( const int a_key ) { key = a_key; }
void DNode::set_prev( const DNode& a_prev ) { prev = &a_prev; }
void DNode::set_next( const DNode& a_next ) { next = &a_next; }

我收到以下错误消息

dnode.cpp:6:89: 错误:无法初始化类型的成员子对象 'DNode *' 右值类型为 'const DNode *' DNode::DNode( const int a_key, const DNode& a_prev, const DNode& a_next) : key(a_key), 上一个(&a_prev),下一个(&a_next){}

dnode.cpp:6:104:错误:无法初始化成员 “DNode *”类型的子对象,右值类型为“const DNode *” DNode::DNode( const int a_key, const DNode& a_prev, const DNode& a_next ) : key(a_key), prev(&a_prev), next(&a_next) {}

dnode.cpp:15:52: 错误: 分配给'DNode *' from 不兼容类型 'const DNode *' void DNode::set_prev( const DNode& a_prev ) { prev = &a_prev; }

dnode.cpp:16:52:错误:从不兼容的类型分配给“DNode *” 'const DNode *' void DNode::set_next( const DNode& a_next ) { next = &a_next; }

再一次,我在构造函数的参数列表中写const DNode& a_prev的原因是因为我想防止a_prev被构造函数修改(但我不在乎它是否被外部修改)。但由于它不起作用,我可能误解了const 在这种情况下的用法。

【问题讨论】:

  • 如何将参数传递给构造函数?
  • 我刚刚编辑了您的构造函数代码,将其分成两行,使其更具可读性。

标签: c++ pointers constants parameter-passing


【解决方案1】:

我认为在你的类中你有数据成员(你没有显示),定义如下:

DNode* prev;
DNode* next;

在构造函数中,您有const DNode* 参数(a_preva_next):

DNode::DNode(const int a_key, const DNode* a_prev, const DNode* a_next) 
   : key(a_key), prev(a_prev), next(a_next) {}

const DNode* 参数意味着您有一个指向DNode 的指针,即const,即不能修改指向的DNode
但是您想将其分配给DNode*const 的数据成员(即DNode 指向可以被修改)。
您不能将限制为 const(即无法修改)的内容分配给非 const 的内容(即可以修改)。

以下代码应该可以工作:

// Remove 'const' from the pointers!
DNode::DNode(const int a_key, DNode* a_prev, DNode* a_next) 
  : key(a_key), prev(a_prev), next(a_next) {}

如果你想在输入参数上使用这种“const”样式,比如const int a_key,你应该把const放在指针符号(*)和参数名称之间,例如

// Proper placing of 'const'
DNode::DNode(const int a_key, DNode* const a_prev, DNode* const a_next) 
  : key(a_key), prev(a_prev), next(a_next) {}

这意味着a_preva_next 不能重新分配以指向其他数据;但它们确实指出了一些可以修改的DNode*)。

【讨论】:

  • 谢谢。从参数中删除 const 时,它确实编译了。我想我在这种情况下误解了const 的含义。我认为这意味着“该参数不应被函数调用修改”。但实际上它似乎意味着“该参数是一个const 对象,不应该被修改,独立于函数调用”。这是正确的吗?
  • @jfk916:这取决于您将const 放在哪里。如果有const X* p,则表示X指向的实例是const,但p可以修改为例如指向不同的东西。如果你有X * const p,这意味着p 不能被修改(并且不能指向不同的东西),但X 指向的东西可以被修改(是非常量)。如果您有const X * const p,则pX 都是const,并且无法修改。
  • @jfk916:如果您觉得答案有帮助,请考虑投票 +1。
【解决方案2】:

您正在尝试使用指向 const 对象的指针初始化指向非 const 对象的指针。 也许您想将 const 指针传递给非 const 对象?那么它将是DNode* const a_prev

【讨论】:

    【解决方案3】:

    看起来DNode 成员a_preva_next 是指向非常量对象的指针。 几个选项:

    • 将这些成员变成指向 const 对象的指针
    • 将成员放入堆栈,并在初始化列表中传递取消引用的参数,以调用复制构造函数。*
    • 堆分配构造函数中的成员并将取消引用的参数传递给复制构造函数调用。*
    • 为这些指针采用非常量参数。

    (*看起来你正在尝试编写一个双向链表,在这种情况下你不想保存其他节点的副本,并且它可以方便上一个和下一个节点能够成为null,保留选项 1 或 4。)

    【讨论】:

      猜你喜欢
      • 2014-06-26
      • 1970-01-01
      • 2016-04-15
      • 1970-01-01
      • 1970-01-01
      • 2015-10-22
      • 1970-01-01
      • 1970-01-01
      • 2018-01-20
      相关资源
      最近更新 更多