class a //my base abstract class
{
public:
virtual void foo() = 0;
};
class b : public a //my child class with new member object
{
public:
void foo()
{}
int obj;
};
int main()
{
b bee;
a * ptr = &bee;
ptr->obj; //ERROR: class a has no member named "obj"
}
我的问题是,当我指向指向子类(“b”)对象的基类(“a”)时,如何访问“obj”成员?我知道铸造应该可以解决问题,但我正在寻找更好的解决方案。
答案 0 :(得分:7)
您可以使用dynamic_cast<>
运算符将指向a
的指针转换为指向b
的指针。仅当ptr
指向的对象的运行时类型为b
时,转换才会成功,否则将返回空指针,因此您必须在转换后检查结果:
b* p = dynamic_cast<b*>(ptr);
if (p != nullptr)
{
// It is safe to dereference p
p->foo();
}
但是,如果可以保证ptr
指向的对象类型为b
,则在这种情况下(因为不涉及虚拟继承),您甚至可以使用{{1}因为它是在编译时执行的,所以会产生较少的开销。
static_cast<>
答案 1 :(得分:3)
您必须抛弃继承层次结构。您的案例是根据适当的类型使用dynamic_cast
量身定制的,因为如果您尝试实际投射的对象具有预期类型,则允许您以类型安全的方式签入。
答案 2 :(得分:1)
在GCC和Clang(我认为在Visual Studio中)你也可以使用以下语法糖
if (Derived* x = dynamic_cast<Derived*>(x)) {
// do something with \c x now that we know its defined
}
在C ++ 11中,使用auto
类型推断,甚至更好
if (auto x = dynamic_cast<Derived*>(x)) {
// do something with \c x now that we know its defined
}
最后,如果我们想限制为只读访问
if (const auto x = dynamic_cast<Derived*>(x)) {
// read something from \c x now that we know its defined
}
请注意,这很好地将x
的范围限制在if子句内部,如果我们使用if
并且使用else if
并且使用{{1}}进行多个连续的dynamic_cast,则通常会更方便。 {{1}}&#39; S