C++,当有一个指针或引用,但是不知道其指向对象的真实类型是什么时,可以调用虚函数完成特定类型对象的行为。但是有时候,我们需要根据不同的数据构造不同的对象类型,相当于虚拟的构造函数。
1.虚拟构造函数
虚拟构造函数是指能够根据输入给穹的数据的不同而建立不同类型的对象。虚拟构造函数可应用于从磁盘(或者通网络连,或者从磁带机上)读取对象信息构造不同类型对象。例如需要编写一个程序,用业进行新闻报道的工作,每一条新闻报道都由文字或图片组成。其具体实现代码如下:
1 class NLComponet 2 { 3 public: 4 ... 5 }; 6 7 class TextBlock:public NLComponent 8 { 9 public: 10 ... 11 }; 12 class Graphic:public NLComponent 13 { 14 public: 15 ... 16 }; 17 class NewsLetter 18 { 19 public: 20 NewsLetter(istream& str); 21 ... 22 private: 23 static NLComponent* readComponent(istream& str); 24 25 list<NLComponent*> components; 26 }; 27 28 NewsLetter::NewsLetter(istream& str) 29 { 30 while(str) 31 { 32 components.push_back(readComponent(str)); 33 } 34 }
readComponent函数,根据所读取的数据建立一个的对象,或是TextBlock或是Graphic,它能建立新对象,行为与构造函数相似,而且可以建立不同类型的对象,因而readComponent函数就是虚拟构造函数。
2.虚拟拷贝构造函数
虚拟拷贝构造函数是一种特殊种类的虚拟构造函数,它能返回一个指针,指向调用该函数的对象的新拷贝。具体实现如下:
1 class NLComponent 2 { 3 public: 4 virtual NLComponent* clone() const = 0; 5 ... 6 }; 7 class TextBlock:public NLComponent 8 { 9 public: 10 virtual TextBlock* clone() const 11 { 12 return new TextBlock(*this); 13 } 14 ... 15 }; 16 class Graphic:public NLComponent 17 { 18 public: 19 virtual Graphic* clone() const 20 { 21 return new Grahpic(*this); 22 } 23 ... 24 };
如上述代码所示,类的虚拟拷贝构造函数只是调用它们真正的拷贝构造函数,因此“拷贝”的含义与真正拷贝构造函数相同。此外,上述代码的实现利用了较宽松的虚拟函数返回值类型规则。被派生类重定义的虚拟函数不用必须与基类的虚拟函数具有一样的返回类型。如果函数的返回类型是一个指向基类的指针(或引用),那么派生类的函数可以返回一个指向基类的派生类的指针(或引用)。
3.非成员函数虚拟化
非成员函数虚拟化是指根据参数的不同动态类型而其行为特性也不同的非成员函数。因为非成员函数不能成为真正的虚拟函数,要实现类似虚拟函数的功能,需要借助真正的虚拟函数。其具体实现方法是:编写一个虚拟函数来完成工作,然后再写一个非虚拟函数,它什么不做只调用这个虚函数。代码如下,为TextBlock和Graphic对象实现一个输出操作符。
1 class NLComponent 2 { 3 public: 4 virtual ostream& print(ostream& s) const = 0; 5 ... 6 }; 7 class TextBlock:public NLComponent 8 { 9 public: 10 virtual ostream& print(ostream& s) const; 11 ... 12 }; 13 class Graphic:public NLComponent 14 { 15 public: 16 virtual ostream& print(ostream& s) const; 17 ... 18 }; 19 inline ostream& operator<<(ostream& s,const NLComponent& c) 20 { 21 return c.print(s); 22 }
上述方法只是根据一个参数让非成员函数虚拟化,那如何实现根据一个以上的参数虚拟化呢?
这个问题可以参考:http://www.cnblogs.com/dwdxdy/archive/2012/08/23/2652875.html
参考资料:More Effective C++