C++ 在基类指针传递参数时检查子类型
我有一个基本的C++ 在基类指针传递参数时检查子类型,c++,C++,我有一个基本的B和它的两个派生类(D1,D2),看起来像这样 struct B { virtual B* DoSomething()=0; }; struct D1:public B { B* DoSomething() { // D1 does something return pD1; } }; struct D2:public B { B* DoSomething() { // D2 does something
B
和它的两个派生类(D1
,D2
),看起来像这样
struct B
{
virtual B* DoSomething()=0;
};
struct D1:public B
{
B* DoSomething()
{
// D1 does something
return pD1;
}
};
struct D2:public B
{
B* DoSomething()
{
// D2 does something
return pD2;
}
};
现在我有了一个函数
void Init(B*pB)
{
if(pB is D1)
{
D1* pD1=down_cast(pB);
pD1->MethodD1();
}
else if(pB is D2)
{
D2* pD2=down_cast(pB);
pD2->MethodD2();
}
else
{
//do something else
}
}
我不想像这样在Init()
方法中检查类型,但不知道还能做什么。这是您的Init()
方法,不在伪代码中:
void Init(B*pB)
{
if(D1 *pD1 = dynamic_cast<D1*>(pB))
{
pD1->MethodD1();
}
else if(D2 *pD2 = dynamic_cast<D2*>(pB))
{
pD2->MethodD2();
}
else
{
//do something else
}
}
void Init(B*pB)
{
如果(D1*pD1=动态_铸造(pB))
{
pD1->method1();
}
否则如果(D2*pD2=动态_铸造(pB))
{
pD2->method2();
}
其他的
{
//做点别的
}
}
如您所见,如果派生类的类型不是您要强制转换的类型,则动态强制转换返回nullptr
您也可以使用引用来实现这一点,在这种情况下,如果类型不是您要强制转换的类型,则dynamic_cast将返回一个异常,因此,由于异常处理不是免费的,因此最好使用指针进行动态强制转换。
还请注意,这是一个运行时检查,而不是编译时检查。这是您的Init()
方法,不是伪代码:
void Init(B*pB)
{
if(D1 *pD1 = dynamic_cast<D1*>(pB))
{
pD1->MethodD1();
}
else if(D2 *pD2 = dynamic_cast<D2*>(pB))
{
pD2->MethodD2();
}
else
{
//do something else
}
}
void Init(B*pB)
{
如果(D1*pD1=动态_铸造(pB))
{
pD1->method1();
}
否则如果(D2*pD2=动态_铸造(pB))
{
pD2->method2();
}
其他的
{
//做点别的
}
}
如您所见,如果派生类的类型不是您要强制转换的类型,则动态强制转换返回nullptr
您也可以使用引用来实现这一点,在这种情况下,如果类型不是您要强制转换的类型,则dynamic_cast将返回一个异常,因此,由于异常处理不是免费的,因此最好使用指针进行动态强制转换。
还请注意,这是一个运行时检查,而不是编译时检查。您确实应该这样做
struct B
{
virtual void Init();
virtual B* DoSomething()=0;
};
struct D1:public B
{
B* DoSomething()
{
// D1 does something
return pD1;
}
void Init()
{
MethodD1();
}
};
struct D2:public B
{
B* DoSomething()
{
// D2 does something
return pD2;
}
void Init()
{
MethodD2();
}
};
在你的主代码中
void Init(B*pB)
{
pB->Init();
}
这就是封装、继承、虚拟方法等的全部要点。您确实应该这样做
struct B
{
virtual void Init();
virtual B* DoSomething()=0;
};
struct D1:public B
{
B* DoSomething()
{
// D1 does something
return pD1;
}
void Init()
{
MethodD1();
}
};
struct D2:public B
{
B* DoSomething()
{
// D2 does something
return pD2;
}
void Init()
{
MethodD2();
}
};
在你的主代码中
void Init(B*pB)
{
pB->Init();
}
这就是封装、继承、虚拟方法等的全部要点。让
method1
和method2
与B
中的方法相同,并且D1
和D2
都覆盖它们,怎么样?如果你真的想明确地发送,你的答案是dynamic\u cast
。你是在寻找还是?也许你想查看typeid是个不好的建议。正确的解决方案是正确使用虚方法。@昆汀:虚方法的问题是Init()接收到一个B*。因此,它无法区分哪个类重写了方法D1或D2,让MethodD1
和MethodD2
与B
中的方法相同,让D1
和D2
都重写如何?如果你真的想明确地发送,你的答案是dynamic\u cast
。你是在寻找还是?也许你想查看typeid是个不好的建议。正确的解决方案是正确使用虚方法。@昆汀:虚方法的问题是Init()接收到一个B*。所以它无法分辨哪个类重写了方法,D1或D2