17 More Effective C++—条款25(构造函数与非成员函数的虚化)

1 构造函数的虚化

1 构造虚函数

构造函数与类的名称相同,因此,此处所指的虚化,并非让构造函数变成虚函数,而是让其具有类似虚函数的行为:

当条件不同时,不同的对象会被创建出来。

下面的代码展示了“虚构造函数”的应用。

class Base {
}
class Derive1 : public Base {
}
class Derive2: public Base {
}

Base* constructObject(std::istream& inStream) {
	Base* obj;
	if (/*condition0*/) {
		// create Base's object
	} else if (/*condition1*/) {
		// create Derive1's object;
	} else {
		// create Derive2's object
	}
	return obj;
}
2 “虚复制构造函数”

如下代码所示。C++11中,虚函数允许返回类型不同,因此,Base, Derive1, Derive2三个类型的clone可以看作时override。这样,每次调用clone函数,可以根据相应的对象,来进行复制。

class Base {
	public:
		virtual Base* clone() const;
}
class Derive1 : public Base {
	public:
		virtual Derive1* clone() const;
}
class Derive2 : public Base {
	public:
		virtual Derive2* clone() const;
}
void func()
{
	std::vector<Base*> objList, targetList;
	for (int idx = 0; idx < objList.size(); ++idx) {
		targetList.push_back(objList->clone());  // 关键代码
	}
}

clone()通常直接调用函数的“复制构造函数”。代码如下:

Base* Base::clone()
{
	return new Base(*this);
}
Derive1* Derive1::clone()
{
	return new Derive1(*this);
}
... 

总结:通过增加一层虚函数clone,我们实现了,根据不同类型来进行复制构造的操作,从而实现多态。

2 非成员函数地虚化

流操作“<<”用于输出内存中的内容。现在,我希望,操作符“<<”能根据不同类型来输出内容。下面将讨论两种情况。

1 类型之间没有关系

比如,我手头有3个类,定义如下。他们之间没有任何关系,那么就需要针对这三个类型,重载"<<"。这样,就可以实现虚化——针对不同类型,能都在运行期间动态调整。

class My1 {
}
class My2 {
}
class My3 {
}
std::ostream operator << (std::ostream& out, const My1& obj);
std::ostream operator << (std::ostream& out, const My2& obj);
std::ostream operator << (std::ostream& out, const My3& obj);

实际上,这与虚函数的定义有一定差别。虚函数需要限定如下几个条件。因此,我们引出第二种情况。

1 “虚”行为,针对的是有继承关系的类。
2 表面上看是基类的行为,实际上可能是子类的行为。
3 基类和子类的行为不完全相同。

2 非成员函数的虚行为

现在有若干水果类,继承与定义关系如下。那么,我们需要根据不同的水果类型,来输出其名字。那么就可以利用虚函数。

class Fruit {
	pulic:
		virtual std::string print();
}
class Apple : public Fruit {
	public:
		virtual std::string print();
}

class BananaApple : public Apple {
	public:
		virtual std::string print();
}
std::ostream operator << (std::ostream& out, const Fruit& obj)
{
	obj.print(); // 根据多态,上面定义的三个类中的print都可以被调用
}

上面重载的<<,展示了我们可以传入基类,然后利用基类的多态性,从而实现非成员函数的多态性。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值