6
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"
}

我的问题是,当我有一个指向基类(“a”)的指针指向子类(“b”)对象时,如何访问“obj”成员?我知道铸造应该可以解决问题,但我正在寻找更好的解决方案。

4

3 回答 3

8

您可以使用dynamic_cast<>运算符将​​指向的指针转换为指向a的指针bptr只有当指向的对象的运行时类型为时,转换才会成功b,否则将返回空指针,因此您必须在转换后检查结果:

b* p = dynamic_cast<b*>(ptr);
if (p != nullptr)
{
    // It is safe to dereference p
    p->foo();
}

但是,如果您可以保证 所指向的对象的类型ptrb,那么在这种情况下(因为不涉及虚拟继承),您甚至可以使用 a static_cast<>,因为它是在编译时执行的,因此开销较小。

b* p = static_cast<b*>(ptr);
// You are assuming ptr points to an instance of b. If your assumption is
// correct, dereferencing p is safe
p->foo();
于 2013-02-11T20:50:54.087 回答
3

您将不得不放弃继承层次结构。您的案例是为使用适当的类型量身定制的,dynamic_cast因为它允许您以类型安全的方式检查您尝试投射的对象是否实际上是预期的类型。

于 2013-02-11T20:47:01.693 回答
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     
}

请注意,这很好地限制了 if 子句内部的范围,如果我们使用's 和'sx一个接一个地执行多个连续的 dynamic_cast,这通常会更方便。ifelse if

于 2013-08-17T21:58:57.677 回答