-1

I am new to C++, I was reading about constructors and I made a program.
Below is the code:

#include<iostream>
using namespace std;
class Demo{
    public:
        int a;
        Demo(int x,int y){
            cout<<"I am default constructor";
        }
        Demo(Demo &c){
            cout<<"I am copy Constructor";
        }
};
int main(){
    Demo c2=Demo(5,7);
    Demo c3=c2;
    cout<<"The value is: "<<c2.a;
}

This code was working fine until I added the copy constructor in class and the second line in the main function. As soon as I added these lines, It shows error in the first line of main function.

The error says:

error: no matching function for call to 'Demo::Demo(Demo)'
note: candidates are:
note: Demo::Demo(Demo&)
note:   no known conversion for argument 1 from 'Demo' to 'Demo&'
note: Demo:Demo(int,int)
note:   candidate expects 2 arguments, 1 provided

My first question is, I am passing two arguments in the constructor then Why the compiler is not able to distinguish and call the correct constructor?
My second question is, If I change the first line of main to be like this:
Demo c2(5,7);
then It works fine. Why is this so?

Thanks in advance for any help you are able to provide

Vinay Yadav
  • 1,206
  • 1
  • 10
  • 19
  • 2
    `Demo(Demo &c)` --> `Demo(const Demo &c)`. A temporary r-value object can't be referenced by a non const reference variable. – 273K Mar 19 '20 at 04:00

2 Answers2

1

My first question is, I am passing two arguments in the constructor then Why the compiler is not able to distinguish and call the correct constructor?

The compiler is calling the Demo(int x,int y) constructor on the right hand side of the line in main,

Demo c2 = Demo(5,7);
        ^ ^
        | |
        | +------- call Demo(int x,int y) to construct an r-value Demo object
        |
        +--------- call Demo(Demo&) copy constructor to construct a Demo object

However, r-values cannot be bound to non-const references. So this line is (attempting to) construct two Demo objects. Only one is succeeding.

r-values can be bound to const references, so the solution is to add const:

Demo(const Demo &c)

My second question is, If I change the first line of main to be like this:
Demo c2(5,7);
then It works fine. Why is this so?

In this case, the appropriate constructor is called. Again, adding const to your copy constructor will clear this up.

JohnFilleau
  • 4,045
  • 1
  • 15
  • 22
  • Thank you very much, Sir, for answering. I think my concept is not clear regarding this. What I knew about this was: The copy constructor is only called when we pass an object in the constructor as I did in second line of main function. I got a fuzzy idea of what's happening here and why the error. But even then these terms like `r-value object` and `const reference variable` not making much sense to me. Can u please suggest me some source from where I can understand these things in depth – Vinay Yadav Mar 19 '20 at 04:29
  • Initializing an object like `T a = b;` will also call the copy constructor, if `b` is of type `T`. Do you have a good C++ book? We have a list.https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list – JohnFilleau Mar 19 '20 at 04:32
  • I don't have a book, I am following one youtube channel playlist Mysirg.com – Vinay Yadav Mar 19 '20 at 04:33
  • I recommend a book. That and answering questions on Stack overflow haha. – JohnFilleau Mar 19 '20 at 04:33
  • Okay, I'll follow a book – Vinay Yadav Mar 19 '20 at 04:37
1

The line

Demo c2=Demo(5,7);

is known as copy initialization. Copy initialization requires calling the copy constructor, which is why you got errors after you added your explicit copy constructor. From cppreference's copy constructor page:

The copy constructor is called whenever an object is initialized (by direct-initialization or copy-initialization) from another object of the same type (unless overload resolution selects a better match or the call is elided), which includes...

Since your copy constructor is

Demo(Demo &c)

this causes a problem as it attempts to bind a non-const lvalue to an rvalue. To resolve this, and the second error, modify your copy constructor to take a const reference

Demo(const Demo &c)

My second question is, If I change the first line of main to be like this: Demo c2(5,7); then It works fine. Why is this so?

In this case, the copy constructor is no longer called. Instead, your overloaded constructor

Demo(int x,int y)

is being called directly, thus the copy constructor is never invoked in this case.