代码之家  ›  专栏  ›  技术社区  ›  Kyle

foo f=foo();//没有与调用“foo::foo(foo)”匹配的函数…哈?

  •  11
  • Kyle  · 技术社区  · 15 年前
    class Foo
    {
    public:
        explicit Foo() {}
        explicit Foo(Foo&) {}
    };
    
    Foo d = Foo();
    

    错误:没有用于调用“foo::foo(foo)”的匹配函数

    我试图改变 Foo(Foo&) Foo(Foo) 正如错误所暗示的,哪个afaik不是有效的构造函数,我确信:

    错误:构造函数无效;您可能是指__foo(const foo&)_

    给出了什么?如何解决此问题?(顺便说一下,这是GCC上的内容)

    10 回复  |  直到 15 年前
        1
  •  12
  •   CB Bailey    15 年前

    在复制构造函数中有两个值得怀疑的地方。

    首先,您已经将复制构造函数显式化了(这是一件值得怀疑的事情),因此(理论上)您需要这样做:

    Foo d( (Foo()) );
    

    其次,复制构造函数接受引用,而不是 const 引用,这意味着您不能将它与临时 Foo .

    就我个人而言,我只是把 explicit 从复制构造函数并使其 康斯特 如有可能,请参考。

    请注意 明确的 对默认构造函数无效。[*] 明确的 只对可以用单个参数调用的构造函数有影响。它防止将它们用于隐式转换。对于只接受零个或两个以上参数的构造函数,它没有效果。

    [注:以下两者之间可能存在差异:

    Foo d;
    

    Foo d = Foo();
    

    但在这种情况下,您有一个用户声明的默认构造函数,因此这不适用。]

    编辑: [*]我已经仔细检查过了,12.3.1[class.conv.ctor]说您可以创建一个默认的构造函数 明确的 . 在这种情况下,构造函数将用于执行 默认初始化 值初始化 . 老实说,我不理解这个值,就好像你有一个用户声明的构造函数,那么它是一个非pod类型,即使是非pod类型的本地对象,如果它们没有一个初始值设定项,这个子句说可以通过 明确的 默认构造函数。也许有人能指出一个角落里的情况,它确实起到了作用,但现在我看不出有什么影响。 明确的 具有默认构造函数。

        2
  •  5
  •   anon    15 年前

    您不希望将这些构造函数中的任何一个标记为显式的-编译器需要隐式地使用这两个构造函数,尤其是复制构造函数。你试图通过明确地标记它们来实现什么?

        3
  •  4
  •   Dima    15 年前

    首先,默认构造函数和复制构造函数都不应该是 explicit . 您只需要创建一个构造函数 明确的 如果它采用其他类型的单个参数,以防止从该类型进行隐式转换。复制构造函数引用类本身,因此不存在不需要的转换的危险。

    其次,确保复制构造函数接受 const 参考文献。

    第三, Foo f; 是使用类foo的默认构造对象的正确方法。注意 Foo f(); 是错误的,因为编译器会将其解释为函数的声明 f() 返回类的对象 Foo .

    第四,如果您已经编写了自己的复制构造函数,那么您还应该编写赋值运算符。

    
    class Foo
    {
      Foo() {} // no need to make explicit.  Nothing to convert from.
    
      Foo(const &Foo f) {} // again, nothing wrong with conversion from Foo to Foo
    
      explicit Foo(int a) {}  // need explicit to prevent accidental passing of an int
                              // to a function that takes Foo as an argument
    };
    
    
        4
  •  3
  •   clahey    15 年前

    尝试不使用显式?我认为:

    Foo foo = Foo()
    

    创建隐式复制,因此不会触发显式复制构造函数。

    编辑:

    这只是答案的一半。参见查尔斯·贝利或叔叔邮报,了解为什么需要警察。

        5
  •  3
  •   UncleBens    15 年前

    复制构造函数不应该是 明确的 (这使得它在这里以及在许多其他完全合理的上下文中都不可计算,例如当按价值传递或返回时)。

    下一步,它应该通过 康斯特 引用,否则它不能绑定到临时对象。

    Foo f = Foo();
            ^^^^^
              |
              --- this is a temporary that cannot be passed to a function
                  that accepts a non-const reference
    

    此外,没有理由设置默认的构造函数 明确的 :此关键字只对只能用一个参数调用的构造函数(复制构造函数除外)有意义,在这种情况下,它会阻止通过该构造函数将其他类型隐式转换为foo。例如,如果一个构造函数 int 明确的 ,这样的情况无法编译:

    Foo f;
    f = 1;  //assuming no operator= overload for (types convertible from) int
            //this implicitly performs f = Foo(1);
    
    Foo g = 10;
    
    void x(Foo);
    x(20);
    

    总而言之:

    class Foo
    {
    public:
        Foo();
        Foo(const Foo&);
        //...
    };
    
    Foo x = Foo();
    

    而且,如果这两个构造函数都不打算做任何事情,那么根本不需要定义它们——编译器将自动提供它们(但是,如果定义任何其他构造函数,则不会自动生成默认的构造函数)。

        6
  •  2
  •   Tom    15 年前
    Foo d = Foo();
    

    应该是

    Foo d;
    

    第一行创建一个foo实例,然后复制到d;

        7
  •  2
  •   Randolpho    15 年前

    你的问题在实例化中。你不需要 Foo d = Foo(); 对于默认构造函数。

    保持类相同,但尝试此方法进行实例化:

    Foo d;
    

    事实上,你甚至不需要 Foo d = Foo(arguments); 用于使用参数进行构造。应该是这样的:

    Foo d(arguments);
    
        8
  •  1
  •   KZ.    15 年前

    编译器告诉你…使用此:

    Foo(const Foo&) {}
    
        9
  •  0
  •   Jerry Coffin    15 年前

    你可以用两种方法来解决这个问题。其中一个(已由伦道夫建议)是消除使用复制系数。另一种方法是写一个适当的复制系数:

    Foo (Foo const &) {}
    

    你通常都想这样做。

    编辑:看看它,我最后的评论很容易被误解。相当多的课程 完全需要一个拷贝连接器,但是 如果 您确实需要一个复制ctor,它通常应该具有上面的形式(不是显式的,并且以一个常量引用作为参数)。

        10
  •  -1
  •   Betamoo    15 年前
    class Foo
    {
    public:
        explicit Foo() {}
        explicit Foo(const Foo&) {}
    };
    
    Foo d = Foo()