Foo f = Foo(); // no matching function for call to 'Foo::Foo(Foo)' … huh?

后端 未结 10 2524
小鲜肉
小鲜肉 2021-02-19 20:13
class Foo
{
public:
    explicit Foo() {}
    explicit Foo(Foo&) {}
};

Foo d = Foo();

error: no matching function for call to \

相关标签:
10条回答
  • 2021-02-19 20:32

    A copy constructor shouldn't be explicit (which makes it uncallable here and in many other perfectly reasonable contexts, such as when passing or returning by value).

    Next it should take the argument by const reference, since otherwise it can't bind to temporaries.

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

    Furthermore, there is no reason to make the default constructor explicit: this keyword only makes sense for constructors (other than the copy constructor) that can be called with exactly one argument, in which case it prevents implicit conversions of other types into Foo via that constructor. For example, if a constructor taking an int were explicit, situations like these wouldn't compile:

    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);
    

    All in all:

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

    And furthermore, if neither of those constructors is meant to do anything, you needn't define them at all - the compiler will provide them automatically (if you define any other constructors, the default constructor will not be automatically generated, though).

    0 讨论(0)
  • 2021-02-19 20:35

    Your problem is in the instantiation. You don't need Foo d = Foo(); for a default constructor.

    Keep your class the same, but try this for instantiation:

    Foo d;
    

    In fact, you don't even need Foo d = Foo(arguments); for constructing with parameters. That should be like this:

    Foo d(arguments);
    
    0 讨论(0)
  • 2021-02-19 20:37

    There are two questionable things that you have in your copy constructor.

    First, you've made the copy-constructor explicit (which is a questionable thing to do), so you would (in theory) need to do:

    Foo d( (Foo()) );
    

    Second, your copy constructor takes a reference and not a const reference which means that you can't use it with a temporary Foo.

    Personally, I'd just remove explicit from the copy-constructor and make it take a const reference if possible.

    Note that the explicit on your default constructor has no effect.[*] explicit only has an effect on constructors that can be called with a single parameter. It prevents them being used for implicit conversions. For constructors that take only zero or only two or more parameters, it has no effect.

    [Note: there can be a difference between:

    Foo d;
    

    and

    Foo d = Foo();
    

    but in this case you have a user-declared default constructor so this doesn't apply.]

    Edit: [*] I've just double checked this and 12.3.1 [class.conv.ctor] says that you can make a default constructor explicit. In this case the constructor will be used to perform default-initialization or value-initialization. To be honest, I don't understand the value of this as if you have a user-declared constructor then it's a non-POD type and even local objects of non-POD type are default-initialized if they don't have an initializer which this clause says can be done by an explicit default constructor. Perhaps someone can point out a corner case where it does make a difference but for now I don't see what effect explicit has on a default constructor.

    0 讨论(0)
  • 2021-02-19 20:37

    You can cure the problem in either of two ways. One (already suggested by Randolpho) is to eliminate using the copy ctor. The other is to write a proper copy ctor:

    Foo (Foo const &) {}
    

    You generally want to do both.

    Edit: Looking at it, my last comment is easy to mis-construe. Quite a few classes do not need a copy ctor at all, but if you do need a copy ctor, it should normally have the form above (not explicit, and taking a const reference as the parameter).

    0 讨论(0)
  • 2021-02-19 20:40

    Try without the explicit? I think that:

    Foo foo = Foo()
    

    creates an implicit copy, thus the explicit copy constructor doesn't get triggered.

    Edit:

    This is only half the answer. See Charles Bailey or UncleBens post for why const is necessary.

    0 讨论(0)
  • 2021-02-19 20:41

    You don't want to mark either of those constructors as explicit - the compiler needs to use both of them, particularly the copy constructor, implicitly. What are you trying to achieve by marking them explicit?

    0 讨论(0)
提交回复
热议问题