Why does this simple C++ class hierarchy fail to exhibit polymorphic behavior?
I'd appreciate it if someone would enlighten me on the following behavior -- I've captured it with a short code example:
//header.h
class base
{
public:
base(int data):data1(data){}
virtual int getData(){return data1;}
private:
int data1;
};
class derived1 :public base
{
public:
derived1(int data):base(data-1),data2(data){}
virtual int getData(){return data2;}
private:
int data2;
};
class derived2 :public derived1
{
public:
derived2(int data):derived1(data-1),data3(data){}
virtual int getData(){return data3;}
private:
int data3;
};
//main.cpp
derived1 d1(20);
derived2 d2(10);
base& baseRefd1 = d1, baseRefd2 = d2;
cout << "call to baseRefd1.getData() yields: " << baseRefd1.getData();
cout << "call to baseRefd2.getData() yields: " << baseRefd2.getData();
derived1& derived1Refd1 = d1, derived1Refd2 = d2;
cout << "call to derived1Refd1.getData() yields: " << derived1Refd1.getData();
cout << "call to derived1Refd2.getData() yields: " << derived1Refd2.getData();
And the output:
call to baseRefd1.getData() yields: 20
call to baseRefd2.getData() yields: 8
call to derived1Refd1.getData() yields: 20
call to derived1Refd2.getData() yields: 9
As you can see, when a base reference is used as a handle to a single level of derivation, we get polymorphism -- the version of getData() called is that of the derived class.
But when the same base reference is used as a handle to a class derived 2 levels away in the hierarchy, there's no polymorphism -- the version of getData called is that of the base.
When a reference of type derived1 is used, i.e. that of the middle level of the hierar开发者_运维知识库chy, there's no polymorphism even when the handle points to a class 1 level away.
I'm sure I need to learn something basic here. Will appreciate any guidance.
base& baseRefd1 = d1, baseRefd2 = d2;
This is the same as
base& baseRefd1 = d1;
base baseRefd2 = d2;
^ baseRefd2 is not a reference!
You need another ampersand:
base& baseRefd1 = d1, & baseRefd2 = d2;
^ this makes baseRefd2 a reference
This is one of the best reasons to follow the rule "only declare one variable at a time, especially when declaring pointers or references."
It is actually possible to declare multiple references without repeating the &
symbol:
template <typename T>
struct reference_to
{
typedef T & type;
};
reference_to<base>::type baseRefd1 = d1, baseRefd2 = d2;
baseRefd2 and derived1Refd2 are not references they are copies.
your variable declaration is to blame. What you wrote, if split to 2 lines looks like:
base& baseRefd1 = d1;
base baseRefd2 = d2;
and
derived1& derived1Refd1 = d1;
derived derived1Refd2 = d2;
(NOTE lack of amp on 2nd declaration in each)
the correct way to declare these on a single line is:
base& baseRefd1 = d1, &baseRefd2 = d2;
derived1& derived1Refd1 = d1, &derived1Refd2 = d2;
(NOTE the new ampersands)
精彩评论