确定性在C++中,对象类型

确定性在C++中,对象类型

问题描述:

让我们假设我有两个具有相同的接口确定性在C++中,对象类型

class FirstChild : class Father 
{ 
    //some fields and methods useful for class A 
} 

class SecondChild : class Father 
{ 
    //some fields and methods useful for class B 
} 

后来,在代码类似的东西做

Father* myInstance = new SecondChild(); 

现在,如果两个类映射两个对象我想知道对象的type,如果实例是FirstChild或SecondChild,则必须执行一些操作。我正在做类似的事情:

if (typeid (myInstance) == typeid (FirstChild)) 
{ 
    // do stuff 
} else if (typeid (myInstance) == typeid (SecondChild)) 
     { 
      // do other stuff 
     } 

这是正确的方式吗? 因为某处StackOverflow,我读了typeid是不是安全,它是更方便地添加一个虚拟功能,比方说getType例如,做,在则firstChild

char* getType { return "FirstChild"; } 

说实话,我不喜欢这样的解决方案太多了,因为我们似乎忽略了面向对象编程中多态的强大功能。

所以,你们,你觉得呢?在C++中检查子对象类型的最佳方法是什么?

+0

'dynamic_cast'也许?无论如何,这样做的需要表明你有严重的设计缺陷。 – user0042

+5

如果你需要知道这种类型,你可能做错了。 – juanchopanza

+1

这听起来像是你应该用多态和虚函数解决的问题。也许'dynamic_cast'。 – NathanOliver

一个简单的方法可以使用dynamic_cast。例如:

Father *myInstance = new SecondChild(); 
SecondChild *casted = dynamic_cast<SecondChild*>(myInstance); 
if (casted != nullptr) 
    std::cout << "myInstance is a SecondChild!"; 
else 
    std::cout << "myInstance is not a SecondChild!"; 

来自:cppreference: dynamic cast

如果转换成功,dynamic_cast的返回类型NEW_TYPE的值。如果转换失败并且new_type是一个指针类型,它将返回该类型的空指针。如果转换失败并且new_type是引用类型,则会抛出一个与std :: bad_cast类型的处理程序匹配的异常。

正如@Rob指出的那样,您可以使用虚拟函数并让对象自己执行操作。

struct Father 
{ 
    virtual void process() = 0; 
}; 

您可以使用虚函数来决定是否应该完成操作,而不是检查类型。

struct Father 
{ 
    virtual bool shouldProcess() { return false; } 
}; 
struct SecondChild : Father 
{ 
    bool shouldProcess() override { return true; } 
} 

有几种方法可以做到这一点。

typeiddynamic_cast<>是做这件事的“官方方式”。

FirstChild *fptr = dynamic_cast<FirstChild>(myInstance); 
if (fptr) { 
    // do something 
} else { 
    SecondChild *cptr = dynamic_cast<SecondChild>(myInstance); 
    if(cptr) { 
    // do something else, and so on... 
    } 
} 

但是,这不是最优雅的方式来做到这一点。

另一种等效的方法是有一个“ID类型”,像枚举或类似。

但正如很多人所说,如果你需要知道什么类型,你可能会做错误的方式。

一个明显的选择是让对象执行特定的操作。假设您在activate()函数中使用此代码。为什么不使用虚拟doAction()

class Father { 
    public: 
     virtual void doAction() = 0; 
} 

//... 
myInstance->doAction(); 

有这种变化,使用不同的设计模式。但我想你明白了。