第五章 构造、析构、拷贝语义学

如下一个abstract base class声明:

class Abstract_base
{
public:
	virtual ~Abstract_base() = 0;
	virtual void interface() const = 0;
	virtual const char*
		mumble() const {return _mumble;}
protected:
	char* _mumble;
};

虽然这个class被设计为一个抽象的base class(其中有pure virtual function,使得Abstract_base不可能拥有实例),但它仍然需要一个显示的构造函数来初始化其data member _memble。如果没有这个初始化操作,derive class的局部成员_memble将无法决定初值,例如:

class Concrete_derived : public Abstract_base
{
public:
	Concrete_derived();
	...
};	 

void foo()
{
	//Abstract_base::_mumble未初始化
	Concrete_derived trouble;
	//...
}

也许Abstract_base 的设计者意图让其每一个derived class 提供_mumble的初值。如果这样,derived class唯一要求就是Abstract_base必须提供带有唯一参数protected constructor:

Abstract_base::Abstract_base(char* mumble_value = 0)
				:_mumble(mumble_value){}

一般而言,class的data member应该被初始化,并且只能在constructor中或在class的其他member functions中指定初值。其他操作破坏封装,使得class的维护和修改更加困难。

也可能说设计者错误并不在于为提供了explicit constructor,而是不应该在抽象的base class中声明data members(把interface和implementation分离),然而将“共享数据”抽象出来放在base class中,也是一红正确的设计。

纯虚函数的存在(Presence of a Pure Virtual Function) 

一个pure virtual function可以被定义和调用,只能静态的调用,不能经由虚拟机制调用:

inline void
Abstract_base:: interface() const
{
	function
	//...
}	 

inline void
Concrete_derived::interface() const
{
	//静态调用
	//调用一个pure virtual function
	Abstract_base::interface();
} 

要不要这么做,全由class设计者决定。唯一的例外就是pure virtual destructor必须定义:每一个derived class destructor会被编译器加以扩张,以静态调用的方式调用其“每一个virtual base class”以及“上一层base class"的destructor,因此只要缺乏任何一个base class destructor定义,就会导致链接失败。

一个好的替代方案就是:不要把virtual destructor声明为pure。

虚拟规格的存在(Presence of a Virtual Specification)

把Abstract_base::mumble()设计为一个virtual function是一个糟糕的选择,因为其函数定义内容并不与类型有关,因为几乎不会被后继的derived class 改写。此外,由于它的non-virtual 函数是个inline函数,如果常常被调用的话,效率上的报应不可谓不轻。

一般而言,把所有的成员都声明成为virtual function,然后再靠编译器的优化操作把非必要的virtual function去除,并不是好的设计理念。

虚拟规格中的const存在

决定一个virtual function是否需要const,似乎是件琐碎的事情。当你真正对一个abstract base class时,却不容易决定。做这件事情:意味着预期subclass实例可能被无穷次数的使用,不把函数声明成const,以为此函数不能够获得一个const reference或const pointer。声明一个const,然后才发现derived instance必须修改某一个data member。最简单的做法就是不声明const。

重新考虑class的声明

由前面讨论,重新定义Abstract_base如下,才是比较合适的一种设计:

class Abstract_base
{
public:
	virtual ~Abstract_base(); //不再是pure
	virtual void interface() const = 0; //不再是const
	 const char*
		mumble() const {return _mumble;} //不再是virtual
protected:
	Abstract_base(char* pc = 0);  //新增一个带唯一参数的constructor
	char* _mumble;
};

猜你喜欢

转载自blog.csdn.net/weixin_28712713/article/details/84126688
今日推荐