构造函数和非成员函数虚拟化
参考<<More Effective C++>>一书中的条款25:"将constructor和non-member function虚化",简单的将里面的代码实现。
constructor虚化:即virtual constructor,是某种函数,视其获得的输入,可产生不同的类型的对象。它在许多情况下有用,其中之一就是从磁盘(或网络或磁带等)读取对象信息。这里我是直接从文件中根据读取到字符的不同构造不同的对象。
non-member function虚化:即一个虚函数做实际工作,再写一个什么都不做的非虚函数,只负责调用虚函数。这里的虚函数即是print()输出函数。
这些类的关系如下图(引用自More Effective C++)
代码如下:
#include "stdafx.h" #include <iostream> #include <fstream> #include <string> #include <list> using namespace std; class NLComponent //抽象基类 { public: virtual ostream& print(ostream& s) const = 0; virtual ~NLComponent(){} }; class TextBlock : public NLComponent //子类一 { public: TextBlock(string name): name(name){} ~TextBlock(); virtual ostream& print(ostream& s) const ; private: string name; //名称 }; ostream& TextBlock::print(ostream& s) const { s<<"TextBlock : "<<name<<endl; return s; } TextBlock::~TextBlock() { cout<<"TextBlock Destroy"<<endl; } class Graphic : public NLComponent //子类二 { public: Graphic(string name): name(name){} ~Graphic(); virtual ostream& print(ostream& s) const ; private: string name; //名称 }; ostream& Graphic::print(ostream& s) const { s<<"Graphic : "<<name<<endl; return s; } Graphic::~Graphic() { cout<<"Graphic Destroy"<<endl; } inline ostream& operator<<(ostream& s, const NLComponent& c) { return c.print(s); } class NewLetter { public: NewLetter(ifstream &fin); ~NewLetter(); void printAll(); private: list<NLComponent*> components; }; NewLetter::NewLetter(ifstream &fin) { string str; while (fin >> str) //根据不同的信息,构造不同的子类对象,即构造函数虚拟化 { if (-1 != str.find("TextBlock")) { components.push_back(new TextBlock(str)); } else if (-1 != str.find("Graphic")) { components.push_back(new Graphic(str)); } } } NewLetter::~NewLetter() { for (list<NLComponent*>::const_iterator it = components.begin(); it != components.end(); ++it) { delete (*it); } components.clear(); } void NewLetter::printAll() { for (list<NLComponent*>::const_iterator it = components.begin(); it != components.end(); ++it) { cout<<**it; //直接输出不同子类的信息,即虚拟化非成员函数 } } int _tmain(int argc, _TCHAR* argv[]) { ifstream fin("components.txt"); NewLetter *letter = new NewLetter(fin); letter->printAll(); delete letter; return 0; }
运行界面:
其中components.txt文件的内容为:
TextBlock1
Graphic1
TextBlock2
Graphic2
TextBlock3
Graphic3
TextBlock4
Graphic4
TextBlock5
Graphic5