在 C++ 中,如何测试对象是不是是父类构造函数中子类的实例?

Posted

技术标签:

【中文标题】在 C++ 中,如何测试对象是不是是父类构造函数中子类的实例?【英文标题】:In C++, how can I test if an object is an instance of a Child class in the Parent class' constructor?在 C++ 中,如何测试对象是否是父类构造函数中子类的实例? 【发布时间】:2011-09-16 00:09:51 【问题描述】:

我试图断言传递给父类的构造函数的指针只有NULL,如果对象是特定使用dynamic_cast的子类类型:

#include <iostream>
class Parent 
public:
    Parent(void *ptr);
    virtual ~Parent(); // to make Parent polymorphic
;

class Child1 : public Parent 
public:
    Child1() : Parent(0)  std::cout << "Child1 ctor\n";;
;
class Child2 : public Parent 
public:
    Child2() : Parent(0)  std::cout << "Child2 ctor\n";;
;

Parent::Parent(void *ptr) 
    if (0 == ptr && 0 == dynamic_cast<Child1*>(this)) 
         std::cerr<<"ERROR\n";
    

Parent::~Parent() ;

int main(void) 
    Child1 *c1 = new Child1();
    Child2 *c2 = new Child2();

打印出来:

ERROR
Child1 ctor
ERROR
Child2 ctor

然而,我希望在Child2 构造期间看到ERROR

为什么当我在从Child1 的构造函数初始化列表调用Child1Parent 构造函数时,dynamic_cast 返回非NULL?另外,有没有其他方法可以完成这个测试?

【问题讨论】:

感觉这样的设计会违反继承的“is-a”关系…… 1) 为什么要这样做? 2)你不能这样做的原因是孩子还没有被构造出来。 因为实际上,我有 10 个不同的子类必须具有非 NULL 指针,但只有 1 个子类将具有 NULL 指针。我试图避免将此检查放在 10 个不同的类中。 @Ross:你为什么不在Parent 中使用静态辅助函数呢? private: static void checkPointer(void *ptr, bool b) if (ptr == NULL &amp;&amp; !b) std::cerr &lt;&lt; "ERROR\n"; . 这仍然违反 D.R.Y. (而且我知道我违反了 KISS :-)),但你给了我一个不同的想法。我可以实现我在访问器方法中编写的 exact 相同的检查,dynamic_cast 将起作用。我想做这个废话的原因是我可以控制ParentChild1,但我无法控制所有其他Child2 ... ChildN 【参考方案1】:

当您在 Parent 构造函数中 - 它是一个基类 - Child 尚未构造。因此,在 Parent 的构造函数中 this 的动态类型将始终是 Parent。

【讨论】:

那么RTTI信息是由每一级构造函数迭代构建的? 不,RTTI 信息是静态的并且在编译时构建。在构造函数和析构函数中,派生类尚未构建或已被销毁。但是你可能会说,对象的动态类型是由每一级构造函数迭代构建的。【参考方案2】:

我猜问题是 dynamic_cast 在 vtable 上工作,直到构造函数完成后才设置。因此,您不能在构造函数中调用 dynamic_cast。

我想不出任何直接的方法来在构造函数中检测到这一点,而无需使用模板并使所有内容都变为静态。你为什么想要这种行为?看起来很可疑 - Parent 真的不应该知道 Child1 和 Child2 的派生词。

如果你想在 Child2 调用父构造函数时防止空指针,为什么不在 Child2 的构造函数中防止它,如果它为空则抛出异常?

【讨论】:

有很多 Child2 的。我试图避免将支票放在一大堆课程中。 为什么不创建一个 CheckedParent 类,并从中派生 Child2s?【参考方案3】:

这样做的一种方法是在基类中创建 proected 构造函数,并传递指示如何初始化它的参数 - 这样子类将决定他们想要它的方式,而基类将根据要求安排事情。

【讨论】:

以上是关于在 C++ 中,如何测试对象是不是是父类构造函数中子类的实例?的主要内容,如果未能解决你的问题,请参考以下文章

条款09:绝不在构造和析构过程中调用virtual函数

C++中,爷类跟父类有相同的函数,用子类对象调用时会产生两义性吗?

在java中子类若要继承父类,需要使用的关键字是啥

java中基类和子类的类型是一样的吗?

子父类构造函数特点

C++中,建立子类对象的时候,会调用基类的构造函数,