0

I will gladly change the title of this thread to something more appropriate once I know what subject this falls under.

If I change the parameters of the error-causing constructor, there is no error.

This error only occurs if I include that exact constructor:

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

Code:

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

}
Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
Kacy
  • 3,330
  • 4
  • 29
  • 57
  • I did include it. It made me format at it as code before posting the question so I included at the top of the code. – Kacy Sep 11 '13 at 23:09
  • @computer This is a very simplified version of my actual code, but the point is, I want to know what the cause of this error is so I can apply that knowledge to my program. – Kacy Sep 11 '13 at 23:11
  • Yep, I noticed that just after I posted my comment ;) I've edited your post slightly to make it obvious (visually) that both message and code are there. – Oliver Charlesworth Sep 11 '13 at 23:12
  • Next time I'll format my question like that, thanks. – Kacy Sep 11 '13 at 23:22

4 Answers4

6

You have declared an unusual and terrible copy constructor, namely one which takes the argument by non-constant reference. This is possible, and it means that no other copy constructor will be defined implicitly. However, it also means that you cannot construct copies from temporary values, since those don't bind to non-constant references.

Unless you had a reason to do what you were doing (maybe you want to define auto_obj :-) ?), you should declare the usual copy constructor with argument Object const & (but make sure to define it correctly!), or just leave it out entirely and rely on the implicitly generated version (as happens when you "comment out the line" in your code); or in C++11 you can default the copy constructor by declaring Object(Object const &) = default;.

(Note that the popular Rule of Three says that you either should not be defining your own, non-trivial copy constructor, or if you do, then you also need a user-defined destructor and assignment operator. Make sure your code is sane.)

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • what about Object o = o.func(); ? – 4pie0 Sep 11 '13 at 23:11
  • 2
    @computer: What about it? – Kerrek SB Sep 11 '13 at 23:12
  • lol I simplified the code as much as I could for people to focus on the error I was getting. Thank you for the explanation, but I don't appreciate someone telling me I have made a "terrible" copy constructor. I should have changed the variable name so you guys wouldn't try to deduce what the point of the code is, and rather deduce the cause of the error. – Kacy Sep 11 '13 at 23:17
  • 2
    @KacyRaye: Appreciate what you will, but a non-const-reference copy constructor *is* terrible. It's massively confusing and almost totally semantically misguided. You can let `auto_ptr` and twenty years of developer ire be a witness to that. – Kerrek SB Sep 11 '13 at 23:18
1

the error you got

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

means that compiler is looking for appropriate copy constructor for class Object. There is no such function in your class definition: your version cannot be used to bind temporary (see below). The correct version might be defined by yourself with:

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

or you can just don't declare such function, and working version will be generated automatically, thus there is no error then as well.


note: you are trying to define Object( Object & toCopy ) {}. This is not correct because taking non-const reference to temporary means you cannot use this temporary object to create a copy from it in your constructor because temporary objects cannot be assigned to non-const reference.

So to express this diferent way:

-> compiler is searching for copy constructor

-> finds your version

-> and this version tells: I will not do it

Finally:

Object o = o.func();

this is not good idea. Referring to nonstatic members of objects that have not been constructed or have already been destructed is undefined behavior. Make func() static so might be used like Object::func() or call it on properly constructed object.

Community
  • 1
  • 1
4pie0
  • 29,204
  • 9
  • 82
  • 118
  • There *is* very much a copy constructor in the OP's code. Just not a suitable one. In fact that's the whole point. You can never *not* have a copy constructor (but it may be explicit/inaccessible/deleted/implicitly-defined/any combination of the above). – Kerrek SB Sep 11 '13 at 23:21
0

Try Object(const Object &toCopy) { }

Michael
  • 5,775
  • 2
  • 34
  • 53
0

As already pointed out by many previously, the problem is that you only defined a copy constructor taking a reference, but the return of the call of o.func(); is an rvalue, which can only bind to rvalue references or const references, not to regular references.

Your code however has another issue, calling func() on o, which at that point is a yet uninitialized object, is a very bad idea. Maybe you intended to implement the factory idiom? In this case I would advise that you declare Object func(); static, and call it from the scope of Object, like so:

Object o = Object::func();
brunocodutra
  • 2,329
  • 17
  • 23