Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C+的优雅解决方案+;多态遗传问题_C++_Inheritance_Polymorphism - Fatal编程技术网

C++ C+的优雅解决方案+;多态遗传问题

C++ C+的优雅解决方案+;多态遗传问题,c++,inheritance,polymorphism,C++,Inheritance,Polymorphism,想象一下,我们正在使用的图书馆有两个类:Dog和Bowl class Bowl; class Dog { Bowl* m_bowl; }; class Bowl { Dog* m_owner; }; 狗拥有一个指向其关联碗对象的指针。Bowl还拥有一个指向其关联Dog对象的指针。一切都很好。现在,我派生了一个新类FancyDog,它扩展了Dog的功能 class FancyDog : public Dog { // Do the fancy dog stuff }

想象一下,我们正在使用的图书馆有两个类:Dog和Bowl

class Bowl;

class Dog
{
    Bowl* m_bowl;
};

class Bowl
{
    Dog* m_owner;
};
狗拥有一个指向其关联碗对象的指针。Bowl还拥有一个指向其关联Dog对象的指针。一切都很好。现在,我派生了一个新类FancyDog,它扩展了Dog的功能

class FancyDog : public Dog
{
     // Do the fancy dog stuff
};
一切都很好,至少在FancyDog需要用一个新的闪亮豪华的碗来替换她那无聊的、旧的普通碗之前是这样

class FancyBowl : public Bowl
{
    // Extra functions only relevant for FancyBowls
};
FancyDog应该如何与其新的FancyBowl交互?我只能想到两个选择,两个都“不错”,但都不是很令人满意

  • FancyDog除了通过Dog继承的碗指针对象外,还拥有一个FancyBowl指针。从技术上讲,它们可能属于不同的类,但从概念上讲,FancyDog现在拥有指向同一对象的两个不同指针,这不会让我觉得自己是一个优雅的程序员。如果我们是学究,我们也在浪费记忆,无可否认,在大多数情况下,这是微不足道的

  • 每次需要访问派生接口时,FancyDog dynamic都会将其Bowl指针强制转换为FancyBowl指针。如果我们只需要做一到两次,那么性能上的冲击可能不是什么大不了的,但这也不会让我感到温暖和模糊

  • 这仅仅是一个经典的性能内存权衡,还是有更优雅的解决方案


    请注意,如果我们试图让FancyBowl跟踪狗,我们也会遇到同样的问题。

    这是狗/碗作者设计不佳的问题。考虑下面的改进:

    class Bowl;
    
    class Dog
    {
        virtual Bowl* getBowl() = 0;
    };
    
    class Bowl
    {
        Dog* m_owner;
    };
    
    现在,FancyDog的一个实现可以保存一个FancyBowl并返回一个指向它的指针,这没有问题

    本质上,问题在于差异——因为Dog类保留了分配给
    m_bowl
    指针的权利,所以不能保证它总是指向FancyBowl,因为Dog可能会重新分配它。在第一种情况下,您保证FancyDog始终有一个FancyBowl,但是您失去了狗和FancyDog看到同一个碗的保证。在第二种情况下,你不知道碗会是一个花式猫头鹰,但你知道你至少总是使用同一个碗


    如果Dog类声明了一个更简单的接口,该接口只需要类实际需要的内容(即,您有一个碗可供它读取),那么问题就消失了。如果您不喜欢简单的运行时多态getter,那么上面还有更复杂的静态变体。

    不要使用原始指针是我能给出的最贴切的建议。FancyBowl是Bowl的孩子。让任何需要区分Bowl和FancyBowl的方法都是虚拟的有什么不对?这样,您只需保证FancyDog对象是使用/给定FancyBowl指针构造的。老实说,这种设计更像是没有正确地进行抽象。也许简单继承无法正确地建模这种关系。狗可以在它的碗上专门化,并假设它至少有
    碗的接口。@πάνταῥεῖ 我查看了原始指针,但所有权/生命周期不是这里的问题。非常清楚的解释,谢谢!在我的特殊情况下,改变图书馆需要做很多工作,但我确实学到了很多+你的名字太相关了!你有没有可能为你提到的静态变量提供一个链接或搜索关键字,这样我就可以快速查看一下,看看我是否能理解它?