关闭

条款二十五:将constructer和nonmember function虚化

标签: C++虚构造函数
114人阅读 评论(0) 收藏 举报
分类:

条款二十五:将constructer和nonmember function虚化

1. 虚化构造函数

  当看到将构造函数虚化时你可能想到C++语法不是只支持析构函数的虚化而不允许构造函数的虚化吗?其实这里说的是将构造函数虚化,不是构建虚构造函数。我们可以想象一个场景,我们开发了一个处理服务器的软件,内容为文字,图片,视频等我们将程序中这些数据的管理设计为下面的代码:

    class data_object
    {
    public:
        virtual void operate() = 0;
    };

    class text:public data_object
    {
    public:
        virtual void operate();
    }

    class photo:public data_object
    {
    public:
        virtual void operate();
    };

    class data_manager
    {
    private:
        std::list<data_object*> _data_list;
    }

  而数据储存在服务器的磁盘上我们需要通过从磁盘上读取数据可能代码如下:

    class data_manager
    {
    private:
        std::list<data_object*> _data_list;
    public:
        data_manager(istream& str)
        {
            while(1)
            {
                //TODO:read data from disk and insert into list
            }
        }
    };

  如果我们将数据的读取交由一个函数去做,代码就会变成:

    class data_manager
    {
    private:
        std::list<data_object*> _data_list;
    public:
        static data_object* read_data(istream& str);
        data_manager(istream& str)
        {
            while(1)
            {
                //TODO:read data from disk and insert into list
                _data_list.push_back(read_data(str));
            }
         }
     };

  read_data函数的作用就是根据从磁盘输入的数据类型生成对应的类的类型,这就是一个虚构造函数尽管他不是虚函数但是完成了虚函数可以完成的功能。在这里构造函数将自己无法完成的功能外包出给成员函数,就如同现实生活中的外包公司一般完成一些额外的任务。
  另一中虚构造函数就是虚拷贝构造函数,徐拷贝构造函数会返回一个自身的指针,指向自身的一个副本,代码如下:

    class object
    {
    public:
        virtual object* clone() const = 0;
    }

    class dialog:public object
    {
    public:
        virtual dialog* clone() const
        {
            return new dialog(*this);
        }
    }

    class widget:public object
    {
    public:
        virtual widget* clone() const
        {
            return new widget(*this);
        }
    }

  从代码中可以看到虚拷贝构造函数其实就是调用了一个拷贝构造函数而已,他的行为取决于类的拷贝构造函数,如果在环境中只是进行简单的浅拷贝,那么clone的行为会紧跟拷贝构造函数,如果需要深拷贝clone的行为亦然。也就是说保留这之前我们谈到过的缓时评估。
  上述虚拷贝构造函数能够成功的原因是C++中允许继承类也就是子类重新定义基类也就是父类中的虚函数时使用与父类不同的返回值,但是返回值必须存在继承关系,如果两个虚函数的返回值一个是int另一个是void就会编译错误!

2. 虚化无成员函数(non-member function)

  对于无成员函数的虚化可以让无成员函数也拥有多态的性质,但是如果仅仅是按照一般的函数设计就会出现一些不方便的地方比如,根据类的类型重载<<操作符:

    class father
    {
    public:
        virtual ostream& operator<<(ostream& os) const
        {
            os<<"father out!\n";
            return os;
        }
    };

    class son:public father
    {
    public:
        virtual ostream& operator<<(ostream& os) const
        {
            os<<"son out!\n";
            return os;
        }
    };

  上述代码可以实现对应的功能但是调用方式就不是那么的方便了。必须按照以下方式调用:

    father fh;
    son    s;
    s<<cout;
    fh<<sout;

  这明显和我们习惯的调用方式有所差距。另一中简单的办法是将打印的功能封装为一个成员函数让这个操作符重载函数调用这个封装的函数比如

    #include<iostream>
    using namespace std;

    class object
    {
    public:
        virtual ostream& print(ostream& os) const = 0;
    };

    class dialog:public object
    {
    public:
        virtual ostream& print(ostream& os) const
        {
            std::cout<<"dialog run!\n";
        }
    };

    class widget:public object
    {
    public:
        virtual ostream& print(ostream& os) const
        {
            std::cout<<"widget run!\n";
        }
    };

    inline ostream& operator<<(ostream& os,const object& ob)
    {
        return ob.print(os);
    }

    int main(int arg,char* ar[])
    {
        dialog dlg;
        widget w;

        cout<<dlg;
        cout<<w;

        return 0;
    }

  代码中将打印工作封装再由重载操作调用完成更好的包装。

0
0

猜你在找
【直播】机器学习&数据挖掘7周实训--韦玮
【套餐】系统集成项目管理工程师顺利通关--徐朋
【直播】3小时掌握Docker最佳实战-徐西宁
【套餐】机器学习系列套餐(算法+实战)--唐宇迪
【直播】计算机视觉原理及实战--屈教授
【套餐】微信订阅号+服务号Java版 v2.0--翟东平
【直播】机器学习之矩阵--黄博士
【套餐】微信订阅号+服务号Java版 v2.0--翟东平
【直播】机器学习之凸优化--马博士
【套餐】Javascript 设计模式实战--曾亮
查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:14110次
    • 积分:666
    • 等级:
    • 排名:千里之外
    • 原创:55篇
    • 转载:0篇
    • 译文:1篇
    • 评论:2条
    文章分类
    最新评论