0

Consider below code which I have written:

#include <iostream>

using namespace std;

class Sample{
    int a;
    public:
    Sample(){a=0;cout << "Sample Created (Default Constructor)" << endl;}
    Sample(int n):a(n){cout << "Sample Created" << endl;}
    ~Sample(){ cout << "Sample destroyed" << endl;}
    Sample(Sample& s){a=s.getA(); cout << "Sample Copy Constructor called" << endl;}
    Sample& operator= (Sample& s){this->a=s.getA(); cout << "Assignment Operator Called" << endl;return (*this);}
    void setA(int n){ a=n;}
    int getA(){return a;}
    };

class Test{
    Sample k;
    public:
    Test(){ cout << "Test Created(Default Constructor)" << endl;}
    Test(Sample& S):k(S){ cout << "Test Created" << endl;}
    ~Test(){cout << "Test Destroyed" << endl;}
    Test& operator= (Test& test){ k = test.getK(); cout << "Test Assignement Operator called" << endl; return (*this); } // Here 1
    Test(Test& test){k=test.getK();cout << "Test Copy Constructor called" << endl;}
    Sample getK(){return k;} // Here 2
    void setK(Sample& s){k=s;}
    };

int main()
{
    Sample a1(5);
    //Sample a2,a4;
    //a2=a1=a4;
    //Sample a3(a2);
    Test b1(a1);
    Test b2=b1;
    //b2=b1;

    return 0;
    }

I am getting below error while compilation:

$ g++ -Wall Interview.cpp -o Interview
Interview.cpp: In member function `Test& Test::operator=(Test&)':
Interview.cpp:23: error: no match for 'operator=' in '((Test*)this)->Test::k = Test::getK()()'
Interview.cpp:12: note: candidates are: Sample& Sample::operator=(Sample&)
Interview.cpp: In copy constructor `Test::Test(Test&)':
Interview.cpp:24: error: no match for 'operator=' in '((Test*)this)->Test::k = Test::getK()()'
Interview.cpp:12: note: candidates are: Sample& Sample::operator=(Sample&)

When I make changes to here 2 as - Sample& getK(){return k;} it compiles perfectly.

Can someone explain why so?

Also at here 1 if the function is defined as Test& operator= (const Test& test){ k = test.getK(); cout << "Test Assignement Operator called" << endl; return (*this); }

I am getting error-

$ g++ -Wall Interview.cpp -o Interview
Interview.cpp: In member function `Test& Test::operator=(const Test&)':
Interview.cpp:23: error: passing `const Test' as `this' argument of `Sample& Test::getK()' discards qualifiers

Why so?

Gaurav K
  • 2,864
  • 9
  • 39
  • 68

2 Answers2

3

First, your copy constructors and assignment operators take non-const lvalue references. For example,

Test& operator= (Test& test)

This means that temporaries cannot bind as arguments to these constructors/operators. The canonical signature uses const references for this reason, and because it makes no sense to mutate the operand:

Test& operator= (const Test& test)
                 ^^^^^

This will allow binding to temporaries:

Test foo () { return Test(); }

Test t0;
t0 = foo();

Second, your "getters" need to be const, so that they can be called on const instances, or via const pointers or references:

Sample getK() const {return k;}
              ^^^^^
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
juanchopanza
  • 223,364
  • 34
  • 402
  • 480
1

You have defined these operators:

Sample& Sample::operator= (Sample& s);
Test& Test::operator= (Test& test);

When a is any Sample, a = b; is the same as a.operator= (b);. This is only valid if b is a Sample&. The return value from getK is a temporary Sample, and non-const lvalue references (in other words, Sample& variables) to temporaries are not permitted see this question.

If you make getK return a lvalue reference to a Sample (Sample&), then there is no problem passing it to your assignment operator. Alternatively, if your assignment operator took a const lvalue reference (const Sample&) there would be no problem binding it to the temporary object.

Community
  • 1
  • 1
user253751
  • 57,427
  • 7
  • 48
  • 90