常见错误53:对于虚基类(子对象)进行默认初始化
(一个class对象中的)虚基类的子对象和非虚基类的子对象,布局是不同的。非虚基类型
子对象的典型布局会如同它是派生类类型一个普通数据成员一样。
而虚基类类型子对象仅在对象中出现一次,哪怕它在构成完整对象的class阶栅(lattice即
继承谱系)中出现多次也不例外。
典型地,存放虚基类子对象的共享存储是附在完整对象之后的。
只有景深派生类才可能知晓虚基类子对象的精确地址。
只有当一个设计清楚彰显了虚基类的使用场合时,才是它出场的最佳时机。
打算被用作虚基类的class,最好还是实现成接口类。
不允许使用静态的向下强制类型转换操作(static downcast)将虚基类对象转换至其派生类
类型。
virtassign.cpp
#include <iostream>
// Uncomment only one of the following!
//#define NONVIRTBASE
#define VIRTBASE
class A {
public:
A( int x = 9999 )
: a( x ) {}
virtual ~A();
void print() const
{ std::cout << "A: " << a; }
private:
int a;
};
inline A::~A()
{}
#ifdef NONVIRTBASE
class B : public A {
public:
B( int a, int x )
: A( a ), b( x ) {}
B &operator =( const B &rhs ) {
if( this != &rhs ) {
b = rhs.b;
}
return *this;
}
void print() const
{ std::cout << "B: " << b << " "; A::print(); }
private:
int b;
};
class C : public A {
public:
C( int a, int x )
: A( a ), c( x ) {}
C &operator =( const C &rhs ) {
if( this != &rhs ) {
c = rhs.c;
}
return *this;
}
void print() const
{ std::cout << "C: " << c << " "; A::print(); }
private:
int c;
};
class D : public B, public C {
public:
D( int a, int b, int c, int x )
: B( a, b ), C( a, c ), d( x ) {}
D &operator =( const D &rhs );
void print() const
{ std::cout << "D: " << d << " "; B::print(); std::cout << " "; C::print(); std::cout << std::endl; }
private:
int d;
};
D &D::operator =( const D &rhs ) {
if( this != &rhs ) {
B::operator =( *this ); // 对B类型 子对象赋值
C::operator =( *this ); // 对C类型 子对象赋值
//对D特定的数据成员 赋值
d = rhs.d;
}
return *this;
}
#endif
#ifdef VIRTBASE
class B : public virtual A {
public:
B( int a, int x )
: A( a ), b( x ) {}
B &operator =( const B &rhs ) {
if( this != &rhs ) {
b = rhs.b;
}
return *this;
}
void nonvirtAssign( const B &that )
{ b = that.b; }
void print() const
{ std::cout << "B: " << b << " "; A::print(); }
private:
int b;
};
class C : public virtual A {
public:
C( int a, int x )
: A( a ), c( x ) {}
C &operator =( const C &rhs ) {
if( this != &rhs ) {
c = rhs.c;
}
return *this;
}
void nonvirtAssign( const C &that )
{ c = that.c; }
void print() const
{ std::cout << "C: " << c << " "; A::print(); }
private:
int c;
};
class D : public B, public C {
public:
D( int a, int b, int c, int x )
: B( a, b ), C( a, c ), d( x ) {}
D &operator =( const D &rhs );
void print() const
{ std::cout << "D: " << d << " "; B::print(); std::cout << " "; C::print(); std::cout << std::endl; }
private:
int d;
};
D &D::operator =( const D &rhs ) {
if( this != &rhs ) {
A::operator =( *this ); // 对虚基类子对象A赋值
B::nonvirtAssign( *this ); // 对 B 类型子对象赋值, 除了 A 部分
C::nonvirtAssign( *this ); // 对 C 类型子对象赋值, 除了 A 部分
// 对D特有的数据成员赋值
d = rhs.d;
}
//继承谱系中的最深派生类应该完成虚基类子对象的赋值,同时应该想方设法阻止位于
//(最深派生类和虚基类子对象的层次) 之间的那些基类子对象重复执行(对于虚基类子
//对象的)赋值操作。
return *this;
}
#endif
int main() {
D d( 0, 1, 2, 3 );
d.print();
D e( d );
e.print();
d = e;
d.print();
getchar();
return 0;
}
输出
D: 3 B: 1 A: 9999 C: 2 A: 9999
D: 3 B: 1 A: 9999 C: 2 A: 9999
D: 3 B: 1 A: 9999 C: 2 A: 9999