【问题标题】:Why do I get this error when I add another constructor?为什么添加另一个构造函数时会出现此错误?
【发布时间】:2013-09-11 23:05:10
【问题描述】:

一旦我知道它属于哪个主题,我很乐意将这个帖子的标题更改为更合适的名称。

如果我改变了导致错误的构造函数的参数,没有错误。

仅当我包含该确切的构造函数时才会发生此错误:

error: no matching function for call to 'Object::Object(Object)'
note: candidates are: Object::Object(Object&)
note:                 Object::Object()

代码:

#include <iostream>

using namespace std;

class Object {

  public:

    Object() {}     /* default constructor - no problems at all */

    Object( Object & toCopy ) {}  /* Cause of error, but no error when commented out */

    Object func() {  
      Object obj;
      return obj;
    }

};

int main() {

  Object o = o.func();  /* this is the line that the error is actually on */

  return 0;

}

【问题讨论】:

  • 我确实包含了它。它让我在发布问题之前将其格式化为代码,因此我将其包含在代码的顶部。
  • @computer 这是我实际代码的一个非常简化的版本,但重点是,我想知道这个错误的原因是什么,以便我可以将这些知识应用到我的程序中。
  • 是的,我注意到就在我发表评论之后;)我稍微编辑了你的帖子,以便(视觉上)清楚地看到消息和代码都在那里。
  • 下次我会像这样格式化我的问题,谢谢。

标签: c++ constructor compiler-errors


【解决方案1】:

您已经声明了一个不寻常且可怕的复制构造函数,即通过非常量引用获取参数的构造函数。这是可能的,这意味着不会隐式定义其他复制构造函数。但是,这也意味着您不能从临时值构造副本,因为它们不会绑定到非常量引用。

除非你有理由去做你正在做的事情(也许你想定义auto_obj :-) ?),你应该用参数Object const &amp; 声明通常的复制构造函数(但请确保正确定义它! ),或者只是完全忽略它并依赖隐式生成的版本(就像您在代码中“注释掉该行”时发生的那样);或者在 C++11 中,您可以通过声明 Object(Object const &amp;) = default;默认复制构造函数。

(请注意,流行的三法则说您不应该定义自己的非平凡复制构造函数,或者如果您这样做,那么您还需要一个用户定义的析构函数和赋值运算符。确保您的代码是理智的。)

【讨论】:

  • 对象 o = o.func(); 怎么样? ?
  • @computer: 怎么样?
  • 大声笑我尽可能地简化了代码,让人们专注于我遇到的错误。谢谢你的解释,但我不感谢有人告诉我我做了一个“糟糕的”复制构造函数。我应该更改变量名,这样你们就不会试图推断代码的意义,而是推断错误的原因。
  • @KacyRaye:欣赏你的意愿,但非 const-reference 复制构造函数 很糟糕。它非常混乱,几乎完全在语义上被误导。您可以让 auto_ptr 和 20 年的开发者愤怒见证这一点。
【解决方案2】:

你得到的错误

error: no matching function for call to 'Object::Object(Object)'
note: candidates are: Object::Object(Object&)
note:                 Object::Object()

表示编译器正在为类Object寻找适当的复制构造函数。您的类定义中没有这样的功能:您的版本不能用于绑定临时(见下文)。正确的版本可能由您自己定义:

Object(const Object& orig) {
    // and initialize data here, and return 
}

或者你可以不声明这样的函数,工作版本会自动生成,这样也不会出错。


注意: 您正在尝试定义Object( Object &amp; toCopy ) {}。这是不正确的,因为对临时对象进行非常量引用意味着您不能在构造函数中使用此临时对象从它创建副本,因为临时对象不能分配给非常量引用

所以换一种方式来表达:

-> 编译器正在寻找拷贝构造函数

-> 找到你的版本

->这个版本告诉我:我不会这样做

最后:

Object o = o.func();

这不是个好主意。引用尚未构造或已销毁的对象的非静态成员是undefined behavior。将 func() 设为静态,因此可以像 Object::func() 一样使用,或者在正确构造的对象上调用它。

【讨论】:

  • OP 的代码中有 非常多的复制构造函数。只是不是一个合适的。事实上,这就是重点。你永远不能没有有一个复制构造函数(但它可能是显式的/不可访问的/删除的/隐式定义的/以上的任何组合)。
【解决方案3】:

试试 Object(const Object &toCopy) { }

【讨论】:

    【解决方案4】:

    正如之前许多人已经指出的那样,问题是您只定义了一个带引用的复制构造函数,但o.func();的调用返回的是rvalue,它可以仅绑定到 rvalue 引用const 引用,而不绑定到常规 references

    但是,您的代码还有另一个问题,在 o 上调用 func(),此时它是一个尚未初始化的对象,是一个 very bad idea。也许您打算实现工厂习语?在这种情况下,我建议您声明 Object func(); 静态,并从 Object 的范围内调用它,如下所示:

    Object o = Object::func();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-06-13
      • 1970-01-01
      • 1970-01-01
      • 2020-06-30
      • 1970-01-01
      • 1970-01-01
      • 2011-06-06
      相关资源
      最近更新 更多