条款三十三:将非尾端类(non-leaf classes)设计为抽象类(abstract classes)

来源:互联网 发布:阿里云如何挂载数据盘 编辑:程序博客网 时间:2024/06/13 11:20

条款三十三:将非尾端类(non-leaf classes)设计为抽象类(abstract classes)

  假如我们希望管理两个类,他们有以下集成结构:

这里写图片描述

  下面是我们的类的定义:

    class Animal    {    public:        Animal& operator=(const Animal& rst);    };    class Lizard:public Animal    {    public:        Lizard& operator=(const Lizard& rst);    };    class Chicken:public Animal    {    public:        Chicken& operator=(const Chicken& rst);    };    class Animal    {    public:        Animal& operator=(const Animal& rst);    };    class Lizard:public Animal    {    public:        Lizard& operator=(const Lizard& rst);    };    class Chicken:public Animal    {    public:        Chicken& operator=(const Chicken& rst);    };

  现在我们需要实现对象之间的赋值,可以将赋值操作声明为virtual,这样就可以定位到具体的类进行操作。但是又带来一个问题这个代码允许不同类型之间的赋值,但是这样做明显是不对的。一种有效的做法是在对传入函数的指针进行操作之前进行动态类型转换当传入的对象并不是我们期望的时候会抛出bad_cast exception异常这样就可以避免不同类型之间的转换。

    Lizard& Lizard::operator=(const Animal& rst)    {        const Lizard& rst_liz = dynamic_cast<const Lizard&>(rst);        //TODO:...    }

  另一种不需要dynamic_cast支持的方法是 将父对象的赋值重载方法声明为私有的这样也可以达到目的,但是问题是Animal不能赋值给Animal。

    class Animal    {    private:        Animal& operator=(const Animal& rst);    };    class Lizard:public Animal    {    public:        Lizard& operator=(const Lizard& rst);    };    class Chicken:public Animal    {    public:        Chicken& operator=(const Chicken& rst);    };
    Animal ob1, ob2;    ob1 = ob2;          //error 试图调用私有方法

  我们需要考虑的是既然在程序中需要将Animal实例化为什么不可以为三者共同构建一个抽象类,即便逻辑上Aniaml是其他两个类的基类。

这里写图片描述

    class AbstractAnimal    {    protected:        AbstractAnimal& operator=(const AbstractAnimal& rst);    public:        virtual ~AbstractAnimal() = 0;    };    class Animal:public AbstractAnimal    {    public:        Animal& operator=(const Animal& rst);    };    class Chicken:public AbstractAnimal    {    public:        Chicken& operator=(const Chicken& rst);    };    class Lizard:public AbstractAnimal    {    public:        Lizard& operator=(const Lizard& rst);    };

  从上面看出在我们写程序的时候不要简单的从逻辑上直接映射类与类之间的关系,用上面的方法也许是一个不错的选择。

0 0
原创粉丝点击