开发者

Why does this simple C++ class hierarchy fail to exhibit polymorphic behavior?

开发者 https://www.devze.com 2023-01-25 08:56 出处:网络
I\'d appreciate it if someone would enlighten me on the following behavior -- I\'ve captured it with a short code example:

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)

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号