Search code examples
c++classoopvirtual

Why did the copy operator get called?


At the last line myA = foo(myOtherB);, the function will return type an object of type A, thus; it will be like saying `myA = input, But why is the copy constructor is being?

output:

B foo()
 A copy ctor //what calls this?
 A op=

For a copy constructor to be called we will have to use the assignment operator during initialization such as: B newB = myOtherB;

#include <iostream>
using namespace std;

class A {
public:
 A() { cout << "A ctor" << endl; }
 A(const A& a) { cout << "A copy ctor" << endl; }
 virtual ~A() { cout << "A dtor" << endl; }
 virtual void foo() { cout << "A foo()" << endl; }
 virtual A& operator=(const A& rhs) { cout << "A op=" << endl; }
};

class B : public A {
public:
 B() { cout << "B ctor" << endl; }
 virtual ~B() { cout << "B dtor" << endl; }
 virtual void foo() { cout << "B foo()" << endl; }
 protected:
 A mInstanceOfA; // don't forget about me!
};

A foo(A& input) {
 input.foo();
 return input;
}
int main() {
 B myB;
 B myOtherB;
 A myA;
 myOtherB = myB;
 myA = foo(myOtherB);
}

Solution

  • At the last line myA = foo(myOtherB);, the function will return type an object of type B

    Not true. Your function returns an object of type A by value. That means, any value you feed this object to be constructed with will be used to construct a new object of that exact type. So in other words:

    int foo(float a) {
        return a + 0.5;
    }
    
    int u;
    
    u = foo(9.3);
    
    // u has a value of 10
    

    Don't expect u to hold a value that a int cannot.

    Same thing if you use user defined types:

    A foo(A& input) {
     input.foo();
     return input; // this expression returns a new A
                   // using the value of `input`
    }
    
    A myA;
    
    myA = foo(myOtherB);
    
    // why would `myA` be anything else than the value of an A?
    

    So then, what happen here?

    B foo()
     A copy ctor //what calls this?
     A op=
    
    A foo(A& input) {
     input.foo(); // prints B foo, virtual call. a reference to A that
                  // points to an object of subclass type B
    
     return input; // copy `input` into the return value object
    }
    

    Then, the operator= gets called.