gpt4 book ai didi

c++ - 在 OO 设计中避免 RTTI

转载 作者:可可西里 更新时间:2023-11-01 15:39:16 25 4
gpt4 key购买 nike

我最近在某个论坛上看到一个面向对象的设计问题,开始考虑使用 RTTI。然而,这一定是糟糕的设计,但我想不出替代方案。这是一个简单的问题:

使用 OO 概念为以下场景创建 C++ 程序 -

My dog, named Buddy, lives in the backyard. He barks at night when he sees a cat or a squirrel that has come to visit. If he sees a frog, and he is hungry, he eats it. If he sees a frog and he isn't hungry, he plays with it. If he has eaten 2 frogs already, and is still hungry, he will let it go. If he sees a coyote, he crys for help. Sometime his friend Spot stops by, and they chase each other. If he sees any other animal, he simply watches it. I would expect that you would have an animal class, and a cat, dog, squirrel, coyote class that inherits from the animal class.

我开始考虑在 dog 类中使用一个 see() 方法,它接受一个 Animal 参数,然后检查对象的实际类型( Frog 、猫等)并采取所需的行动——玩耍、追逐等,具体取决于实际类型。然而,这将需要 RTTI,这一定是糟糕的设计。任何人都可以提出一个更好的设计来避免 RTTI 并指出我的想法中的错误吗?

最佳答案

根据您想要强调的内容,使用“OO 概念”可以通过多种方式来解决此问题。

这是我能想到的最简单的解决方案:

class Animal {
public:
virtual void seenBy(Buddy&) = 0;
};

class Buddy {
public:
void see(Cat&) { /* ... */ }
void see(Squirrel&) { /* ... */ }
// ...
};

class Cat : public Animal {
public:
virtual seenBy(Buddy& b) { b.see(*this); }
};

class Squirrel : public Animal {
public:
virtual seenBy(Buddy& b) { b.see(*this); }
};

// classes for Frog, Coyote, Spot...

如果您需要多种“感知”动物,可以直接为 see 制作一个虚拟包装器(生成 double dispatch 的形式):

// On a parent class
virtual void see(Animal&) = 0;

// On Buddy
virtual void see(Animal& a) { a.seenBy(*this); }

以上要求 Animal 类了解 Buddy 类。如果您不喜欢您的方法是被动动词,并且想将 AnimalBuddy 分离,您可以使用访问者模式:

class Animal {
public:
virtual void visit(Visitor&) = 0;
};

class Cat : public Animal {
public:
virtual void visit(Visitor& v) { v.visit(*this); }
};

class Squirrel : public Animal {
public:
virtual void visit(Visitor& v) { v.visit(*this); }
};

// classes for Frog, Coyote, Spot...

class Visitor {
public:
virtual void visit(Cat&) = 0;
virtual void visit(Squirrel&) = 0;
// ...
};

class BuddyVision : public Visitor {
public:
virtual void visit(Cat&) { /* ... */ }
virtual void visit(Squirrel&) { /* ... */ }
// ...
};

class Buddy {
public:
void see(Animal& a) {
BuddyVision visitor;
a.visit(visitor);
}
};

第二种机制可以用于 Buddy 看到动物以外的目的(可能是为了让动物看到 Buddy)。然而,它更复杂。


请注意,OO 绝对不是解决此问题的唯一方法。存在可能更适用于此问题的其他解决方案,例如存储导致 Buddy 吠叫、进食、玩耍等的各种动物的属性。这另外将 Buddy 类与 Animal 类(即使是访客模式也需要 Buddy 可以感知的所有内容的详尽列表)。

关于c++ - 在 OO 设计中避免 RTTI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9287357/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com