C++ 具有扩展接口的派生类的集合。如何在没有动态强制转换的情况下访问派生接口?
假设我有一个“动物”类型的抽象对象。动物有公纯虚法“吃” 我想将动物派生为“狗”和“猫”,每个都有一个扩展接口。例如,我希望狗有一个公共方法“chaseTail”,猫有一个公共方法“destroyFurniture” 我想制作一个“世界”对象中的动物集合 我需要能够使用“GetAnimalPosition”方法从世界上检索这些动物,并且能够任意调用chaseTail或销毁我得到的动物上的家具 我想避免缓慢的动态施法,测试位置是否是给定的动物,或是将追逐的尾巴和家具提升到动物身上,但我似乎回到了一个角落C++ 具有扩展接口的派生类的集合。如何在没有动态强制转换的情况下访问派生接口?,c++,oop,C++,Oop,假设我有一个“动物”类型的抽象对象。动物有公纯虚法“吃” 我想将动物派生为“狗”和“猫”,每个都有一个扩展接口。例如,我希望狗有一个公共方法“chaseTail”,猫有一个公共方法“destroyFurniture” 我想制作一个“世界”对象中的动物集合 我需要能够使用“GetAnimalPosition”方法从世界上检索这些动物,并且能够任意调用chaseTail或销毁我得到的动物上的家具 我想避免缓慢的动态施法,测试位置是否是给定的动物,或是将追逐的尾巴和家具提升到动物身上,但我似乎回到了一
还有其他方法吗?您可以在完全了解所有类的情况下执行访问者模式操作。您可以在完全了解所有类的情况下执行访问者模式操作。希望在运行时发现多态层次结构的动态类型通常表明存在设计错误。您可以尝试以下方法:
struct Animal
{
virtual ~Animal() { }
void eat() { doEat(); }
void performTypicalActivity() { doTypical(); }
private:
virtual void doEat() = 0;
virtual void doTypical() = 0;
};
struct Cat : Animal
{
void destroyFurniture();
void purr();
private:
virtual void doTypical() { destroyFurniture(); purr(); }
};
现在,您在集合上迭代,并对每个元素调用
p->performTypicalActivity()
。在运行时发现多态层次结构的动态类型通常表明存在设计错误。您可以尝试以下方法:
struct Animal
{
virtual ~Animal() { }
void eat() { doEat(); }
void performTypicalActivity() { doTypical(); }
private:
virtual void doEat() = 0;
virtual void doTypical() = 0;
};
struct Cat : Animal
{
void destroyFurniture();
void purr();
private:
virtual void doTypical() { destroyFurniture(); purr(); }
};
现在,您迭代您的集合,并对每个元素调用p->performTypicalActivity()
。是一个可行的解决方案。该解决方案有两个主要参与者:
- 元素:具有接受访问者的公共父级的不同类型。在这种情况下,元素是
和Cat
,共同的父元素是Dog
Animal
- Visitor:将访问元素的类,可以调用特定于元素的操作,因为它具有特定元素类型的句柄
Cat::destrofurniture()
和Dog::chaseTail()
:
现在,向Animal
添加一个纯虚拟方法,该方法接受Visitor
作为参数:void Animal::accept(Vistor&)
。其思想是将访问者
传递给动物
,并允许虚拟方法解析为特定的运行时类型。一旦虚拟调用被解析,实现就可以调用Visitor
上的特定visit
方法
class Animal
{
public:
...
virtual void accept( Visitor& ) = 0;
};
class Cat: public Animal
{
public:
...
virtual void accept( Visitor& visitor ) { visitor.visitCat( *this ); }
};
class Visitor
{
public:
virtual void visitCat( Cat& ) = 0;
virtual void visitDog( Dog& ) = 0;
};
class FurnitureDestroyingVisitor: public Visitor
{
virtual void visitCat( Cat& cat ) { cat.destroyFurniture(); }
virtual void visitDog( Dog& dog ) {} // Dogs cannot destroy furniture.
};
注意虚拟方法如何用于解析特定的元素类型,以及每个元素的accept
实现将调用访问者上的方法。这允许执行基于类型的分支,而无需使用dynamic\u cast
,通常称为
是一个可编译的示例,演示了正在使用的模式:
#include <iostream>
#include <vector>
using std::cout;
using std::endl;
class Cat;
class Dog;
class Visitor
{
public:
void visitCat( Cat& cat );
void visitDog( Dog& dog );
};
class Animal
{
public:
virtual ~Animal() {}
virtual void eat() = 0;
virtual void accept( Visitor& ) = 0;
};
class Cat: public Animal
{
public:
void destroyFurniture() { cout << "Cat::destroyFurniture()" << endl; }
void eat() { cout << "Cat::eat()" << endl; }
void accept( Visitor& visitor ) { visitor.visitCat( *this ); }
};
class Dog: public Animal
{
public:
void chaseTail() { cout << "Dog::chaseTail()" << endl; }
void eat() { cout << "Dog::eat()" << endl; }
void accept( Visitor& visitor ) { visitor.visitDog( *this ); }
};
// Define Visitor::visit methods.
void Visitor::visitCat( Cat& cat ) { cat.destroyFurniture(); }
void Visitor::visitDog( Dog& dog ) { dog.chaseTail(); }
int main()
{
typedef std::vector< Animal* > Animals;
Animals animals;
animals.push_back( new Cat() );
animals.push_back( new Dog() );
Visitor visitor;
for ( Animals::iterator iterator = animals.begin();
iterator != animals.end(); ++iterator )
{
Animal* animal = *iterator;
// Perform operation on base class.
animal->eat();
// Perform specific operation based on concrete class.
animal->accept( visitor );
}
return 0;
}
请注意,在本例中,
Visitor
是一个具体的类。但是,可以为访问者
创建整个层次结构,允许您根据访问者
执行不同的操作
class Animal
{
public:
...
virtual void accept( Visitor& ) = 0;
};
class Cat: public Animal
{
public:
...
virtual void accept( Visitor& visitor ) { visitor.visitCat( *this ); }
};
class Visitor
{
public:
virtual void visitCat( Cat& ) = 0;
virtual void visitDog( Dog& ) = 0;
};
class FurnitureDestroyingVisitor: public Visitor
{
virtual void visitCat( Cat& cat ) { cat.destroyFurniture(); }
virtual void visitDog( Dog& dog ) {} // Dogs cannot destroy furniture.
};
访问者模式的一个主要缺点是添加元素
可能需要更改访问者
类。一般的经验法则是:
- 如果元素层次结构可能会更改,那么在基本元素类上定义操作可能会更容易。在本例中,如果需要添加
、奶牛
和马
,则可能更容易向猪
添加虚拟动物
方法点典型
- 如果元素层次结构是稳定的,但是操作元素的算法在变化,那么访问者模式可能是一个很好的候选者
- 元素:具有接受访问者的公共父级的不同类型。在这种情况下,元素是
和Cat
,共同的父元素是Dog
Animal
- Visitor:将访问元素的类,可以调用特定于元素的操作,因为它具有特定元素类型的句柄
- 这是一个可行的解决方案。该解决方案有两个主要参与者:
Cat::destrofurniture()
和Dog::chaseTail()
:
现在,向Animal
添加一个纯虚拟方法,该方法接受Visitor
作为参数:void Animal::accept(Vistor&)
。其思想是将访问者
传递给动物
,并允许虚拟方法解析为特定的运行时类型。一旦虚拟调用被解析,实现就可以调用Visitor
上的特定visit
方法
class Animal
{
public:
...
virtual void accept( Visitor& ) = 0;
};
class Cat: public Animal
{
public:
...
virtual void accept( Visitor& visitor ) { visitor.visitCat( *this ); }
};
class Visitor
{
public:
virtual void visitCat( Cat& ) = 0;
virtual void visitDog( Dog& ) = 0;
};
class FurnitureDestroyingVisitor: public Visitor
{
virtual void visitCat( Cat& cat ) { cat.destroyFurniture(); }
virtual void visitDog( Dog& dog ) {} // Dogs cannot destroy furniture.
};
注意虚拟方法如何用于解析特定的元素类型,以及每个元素的accept
实现将调用访问者上的方法。这允许执行基于类型的分支,而无需使用dynamic\u cast
,通常称为
是一个可编译的示例,演示了正在使用的模式:
#include <iostream>
#include <vector>
using std::cout;
using std::endl;
class Cat;
class Dog;
class Visitor
{
public:
void visitCat( Cat& cat );
void visitDog( Dog& dog );
};
class Animal
{
public:
virtual ~Animal() {}
virtual void eat() = 0;
virtual void accept( Visitor& ) = 0;
};
class Cat: public Animal
{
public:
void destroyFurniture() { cout << "Cat::destroyFurniture()" << endl; }
void eat() { cout << "Cat::eat()" << endl; }
void accept( Visitor& visitor ) { visitor.visitCat( *this ); }
};
class Dog: public Animal
{
public:
void chaseTail() { cout << "Dog::chaseTail()" << endl; }
void eat() { cout << "Dog::eat()" << endl; }
void accept( Visitor& visitor ) { visitor.visitDog( *this ); }
};
// Define Visitor::visit methods.
void Visitor::visitCat( Cat& cat ) { cat.destroyFurniture(); }
void Visitor::visitDog( Dog& dog ) { dog.chaseTail(); }
int main()
{
typedef std::vector< Animal* > Animals;
Animals animals;
animals.push_back( new Cat() );
animals.push_back( new Dog() );
Visitor visitor;
for ( Animals::iterator iterator = animals.begin();
iterator != animals.end(); ++iterator )
{
Animal* animal = *iterator;
// Perform operation on base class.
animal->eat();
// Perform specific operation based on concrete class.
animal->accept( visitor );
}
return 0;
}
请注意,在本例中,
Visitor
是一个具体的类。但是,可以为访问者
创建整个层次结构,允许您根据访问者
执行不同的操作
class Animal
{
public:
...
virtual void accept( Visitor& ) = 0;
};
class Cat: public Animal
{
public:
...
virtual void accept( Visitor& visitor ) { visitor.visitCat( *this ); }
};
class Visitor
{
public:
virtual void visitCat( Cat& ) = 0;
virtual void visitDog( Dog& ) = 0;
};
class FurnitureDestroyingVisitor: public Visitor
{
virtual void visitCat( Cat& cat ) { cat.destroyFurniture(); }
virtual void visitDog( Dog& dog ) {} // Dogs cannot destroy furniture.
};
访问者模式的一个主要缺点是添加El