This program assigns a new object of class A
to reference a
. It looks as expected, reference changes to new object ( see line 23,24,25):
#include <iostream>
using namespace std;
class A {
string name;
public:
A(string n): name(n) {
}
A(): name("NO ONE") {
}
void print() {
cout << "I am "<< name << "!"<< endl;
}
};
int main(int argc, char *argv[]) {
A matrix = A("the matrix");
A &a = matrix;
a.print();
// What happens here?
a = A("neo");
a.print();
}
OUTPUT:
I am the matrix!
I am neo!
However the problem wasn’t apparent until I coded the following inheritance hierarchy.
Consider the following file vitual.cc
which emulates a concept of “Intefrace” from Java world. All went well until I found an un-expected behaviour at lines 53 and 54 highlighted below:
#include <iostream>
using namespace std;
class AbstractInterface {
public:
// constructor
AbstractInterface() {
cout << "AbstractInterface()" << endl;
}
// destructor
virtual ~AbstractInterface() {
cout << "~AbstractInterface()" << endl;
}
virtual void fun() = 0;
};
class A: public virtual AbstractInterface {
public:
void fun() {
cout << "A::fun()" << endl;
}
};
class B: public virtual AbstractInterface {
public:
void fun() {
cout << "B::fun()" << endl;
}
};
class AB: public A, public B
{
public:
void fun() {
cout << "AB::fun()" << endl;
}
};
int main(int argc, char *argv[]) {
AB ab;
A &a = ab;
B &b = ab;
AbstractInterface &i = ab;
ab.fun();
a.fun();
b.fun();
i.fun();
//What happens here?
a = A();
a.fun();
}
OUTPUT:
AbstractInterface()
AB::fun()
AB::fun()
AB::fun()
AB::fun()
AbstractInterface()
~AbstractInterface()
AB::fun()
~AbstractInterface()
The output specific to lines 53 and 54 is:
AbstractInterface()
~AbstractInterface()
AB::fun()
Notice that an Object was created and destroyed immediately before we called a.fun()
. If reference was changed to a new object, it would print A::fun()
instead of AB::fun()
.
What happened here is:
- A new object is created on the stack
- reference assignment calls a copy constructor
- then the object destructor gets called
- the reference still points to old object
According to Thinking in C++ by Bruce Eckel:
There are certain rules when using references:
- A reference must be initialized when it is created. (Pointers can be initialized at any time.)
- Once a reference is initialized to an object, it cannot be changed to refer to another object. (Pointers can be pointed to another object at any time.)
- You cannot have NULL references. You must always be able to assume that a reference is connected to a legitimate piece of storage.
So the concept of reference in C++ and Java/Python/Ruby… is not same!