一. 子对象重叠问题
1. 当继承基类时,在派生类中就得到了基类所有数据成员的副本,该副本称为子对象,如果存在菱形继承,就会出现子对象重叠的情况:
2. 向上二义性
当new mi,并将其传给base*时,由于没办法搞清楚打算使用d1子对象的base还是d2子对象的base作为结果地址,所以编译器将不会受理,如下:
#include <iostream>
#include "Tstash.h"
using namespace std;
class base
{
public:
virtual char* vf() const = 0;
};
class d1 : public base
{
public:
char* vf() const
{
return "d1";
}
};
class d2 : public base
{
public:
char* vf() const
{
return "d2";
}
};
class mi : public d1, public d2{}; //问题1:cause error: ambiguous override of vf()
int main()
{
tstash<base> b;
b.add(new d1);
b.add(new d2);
b.add(new mi); //问题2:error C2594: 'argument' : ambiguous conversions from 'mi *' to 'base *'
for(int i = 0; i < b.count(); i++)
{
cout << b[i]->vf() << endl;
}
system("pause");
return 1;
}
对于问题1,必须对类mi中的函数vf进行重新定义,以消除二义性
对于问题2,着眼于语言层面的扩展,可以进行virtual继承,例如:
#include <iostream>
#include "Tstash.h"
using namespace std;
class base
{
public:
virtual char* vf() const = 0;
};
class d1 : virtual public base
{
public:
char* vf() const
{
return "d1";
}
};
class d2 : virtual public base
{
public:
char* vf() const
{
return "d2";
}
};
class mi : public d1, public d2
{
public:
char* vf() const
{
return d1::vf();
}
};
int main()
{
tstash<base> b(no);
b.add(new d1);
b.add(new d2);
b.add(new mi);
for (int i = 0; i < b.count(); i++)
{
cout << b[i]->vf() << endl;
}
system("pause");
return 1;
}
二. “最晚派生”类和虚基类初始化
所谓“最晚派生类”是指当前所在类,例如:基类构造函数里最晚派生类是base;在d1构造函数里,d1是最晚派生类;在mi构造函数里,mi是最晚派生类。打算使用虚基类时,最晚派生类构造函数的职责是对虚基类进行初始化,这意味着不管该类离虚基类多远,都有责任对虚基类进行初始化,例如:
//virtual base initialization
//virtual base classes must always be initialized by the "most-derived" class
#include <iostream>
#include "Tstash.h"
using namespace std;
class base
{
public:
base(int){}
virtual char* vf() const = 0;
};
class d1 : virtual public base
{
public:
d1() : base(1){}
char* vf() const{return "d1";}
};
class d2 : virtual public base
{
public:
d2() : base(2){}
char* vf() const{return "d2";}
};
class mi : public d1, public d2
{
public:
mi() : base(3){}
char* vf() const
{
return d1::vf();
}
};
class x : public mi
{
public:
x() : base(4){}
};
int main()
{
tstash<base> b(no);
b.add(new d1);
b.add(new d2);
b.add(new mi);
b.add(new x);
for (int i = 0; i < b.count(); i++)
{
cout << b[i]->vf() << endl;
}
system("pause");
return 1;
}
每个子类都要对虚基类进行初始化,这样比较麻烦,可以给虚基类使用缺省构造函数,比如:
#include <iostream>
#include "Tstash.h"
using namespace std;
class base
{
public:
base(int = 0){}
virtual char* vf() const = 0;
};
class d1 : virtual public base
{
public:
d1() : base(1){}
char* vf() const { return "d1"; }
};
class d2 : virtual public base
{
public:
d2() : base(2){}
char* vf() const{return "d2";}
};
class mi : public d1, public d2
{
public:
mi(){}
char* vf() const
{
return d1::vf();
}
};
class x : public mi
{
public:
x(){}
};
int main()
{
tstash<base> b;
b.add(new d1);
b.add(new d2);
b.add(new mi);
b.add(new x);
for(int i = 0; i < b.count(); i++)
{
cout << b[i]->vf() << endl;
}
system("pause");
return 1;
}