gpt4 book ai didi

c++ - 多个派生类的 dynamic_cast

转载 作者:太空狗 更新时间:2023-10-29 23:25:25 25 4
gpt4 key购买 nike

我有一个基类和 n 个派生类。我想实例化一个派生类并将其发送到一个函数,该函数接收一个基类作为参数。在函数内部,我通过dynamic_cast找到了它是什么类型的派生类,但是我不想用几个if-else语句。相反,我想知道是否有办法找出它是哪个派生类以便对其进行转换。 这里我留下我的代码作为例子。

class animal{
public:
virtual ~animal() {}
int eyes;

};

class dog: public animal{
public:
int legs;
int tail;
};

class fish: public animal{
public:
int mostage;
};

void functionTest(animal* a){
if(dynamic_cast<fish*>(a) != NULL){
do_something();
}
else if(dynamic_cast<dog*>(a) != NULL){
do_something();
}
};

我想对此有一个更通用的方法。像 dynamic_cast(a) 这样的东西。谢谢!

最佳答案

如果您需要在几分钟内演示一些东西,那么对于快速草稿这样做是很好的,但通常您会尽量避免以这种方式使用 dynamic_cast - 如果在错误的地方使用它会导致极高的维护成本。可以使用各种模式,例如简单的方法重载、Visitor。模式,或虚拟“GetType”函数(如果您喜欢模式,可以使用 curiously recurring template pattern 实现)。

我将列出所有 3 种方法。第一个是迄今为止最直接、最容易使用的。其他 2 种方法的优点是,它们中的每一种都将决定做什么的决定转移到代码的不同部分,这可能是一个巨大的好处(或缺点)。

让我们假设这是你想要做的:

void functionTest(animal* a)
{
if(dynamic_cast<fish*>(a) != NULL)
blub();
else if(dynamic_cast<dog*>(a) != NULL)
bark();
};

简单的虚函数方法:

class animal {
public:
virtual ~animal() {}
virtual void do_something() = 0;
int eyes;
};

class dog : public animal {
public:
virtual void do_something() { bark(); } // use override in C++11
int legs;
int tail;
};

class fish: public animal {
public:
virtual void do_something() { blub(); } // use override in C++11
int mostage;
};

void functionTest(animal* a)
{
if (a) a->do_something();
};

访客方式:

class IVisitor {
public:
~IVisitor(){}
virtual void visit(const fish&){}
virtual void visit(const dog&){}
virtual void visit(const animal&){}
};

class animal {
public:
virtual ~animal() {}
virtual void accept(IVisitor& visitor) = 0;
int eyes;
};

class dog : public animal {
public:
virtual void accept(IVisitor& visitor) { visitor.visit(*this); } // use override in C++11
int legs;
int tail;
};

class fish : public animal {
public:
virtual void accept(IVisitor& visitor) { visitor.visit(*this); } // use override in C++11
int mostage;
};

class MyVisitor : public IVisitor {
public:
virtual void visit(const fish&) { blub(); } // use override in C++11
virtual void visit(const dog&) { bark(); } // use override in C++11
};

void functionTest(animal* a)
{
if (a)
{
MyVisitor v;
a->accept(v);
}
};

GetType 方法,使用 CRTP香料:

class animal {
public:
virtual ~animal() {}
virtual const type_info& getType() const = 0; // careful. typeinfo is tricky of shared libs or dlls are involved
int eyes;
};

template <class T>
class BaseAnimal : public animal {
// these are C++11 features. Alternatives exist to ensure T derives from BaseAnimal.
static_assert(std::is_base_of<BaseAnimal,T>(,"Class not deriving from BaseAnimal");// C++11

virtual const type_info& getType() const { return typeid(T); }
};

class dog : public BaseAnimal<dog> {
public:
int legs;
int tail;
};

class fish : public BaseAnimal<fish> {
public:
int mostage;
};

void functionTest(animal* a)
{
if (!a)
return;
if (a->getType() == typeid(fish))
blub();
else if (a->getType() == typeid(dog))
bark();
};

请注意,您应该将上述示例视为伪代码。对于最佳实践,您将需要查找模式。此外,奇怪的重复模板模式也可以用在第二种方法中,或者它可以很容易地从第三种方法中删除。这只是为了在这些情况下方便。

关于c++ - 多个派生类的 dynamic_cast,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27451776/

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