C++语言99个常见编程错误 常见错误53:对于虚基类(子对象)进行默认初始化

常见错误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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值