• 构造函数和非成员函数虚拟化


      参考<<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
  • 相关阅读:
    linux设备驱动第五篇:驱动中的并发与竟态
    chromium浏览器开发系列第二篇:如何编译最新chromium源码
    你所不知道的html5与html中的那些事(二)
    vim 高级使用技巧第二篇
    FFMPEG高级编程第一篇:环境搭建及编译
    android apk 防止反编译技术第一篇-加壳技术
    你所不知道的html5与html中的那些事(一)
    交通视频
    Git命令----放弃本地修改使用服务器上的代码
    IE10(去掉文本框的X)
  • 原文地址:https://www.cnblogs.com/venow/p/2726606.html
Copyright © 2020-2023  润新知