2013-02-11 99 views
5
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”成员“)对象?我知道铸造应该做到这一点,但我正在寻找更好的解决方案。使用指针指向基类抽象类的子类成员

+0

有些上下文会有所帮助。你为什么要那样做?如果转换不是选项,则必须在派生类中有一个虚拟函数重写,该重写返回一个引用或指向该成员的指针。但是,这通常会破坏封装。这将我们带回到为什么要通过指向基类的指针访问派生类成员? – Void 2013-02-11 20:50:59

+0

@虚构你可能是对的,我应该改变设计。 – user1873947 2013-02-11 20:53:01

回答

7

您可以使用dynamic_cast<>运算符将指针转换为指向b的指针a。转换将成功的前提条件对象的运行时类型指向ptrb,并将否则返回一个空指针,所以你必须转换后检查结果:

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

如果你能保证由ptr指向的对象的类型是b,但是,在这种情况下(因为不涉及虚拟继承),您甚至可以使用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(); 
3

您必须抛弃继承层次结构。您的情况是为适合的类型使用dynamic_cast而量身定制的,因为您可以以类型安全的方式检查您尝试投射的对象实际上是否具有预期类型。

+0

我没有想到dynamic_cast,它应该解决这个问题,因为它是类型安全的。 – user1873947 2013-02-11 20:48:10

1

在GCC和锵(在Visual Studio中,我认为),您也可以使用下面的语法糖

if (Base* x = dynamic_cast<Base*>(x)) { 
    // do something with \c x now that we know its defined  
} 

和C++ 11,使用auto类型推断,甚至更好

if (auto x = dynamic_cast<Base*>(x)) { 
    // do something with \c x now that we know its defined  
} 

最后,如果我们想限制为只读访问

if (const auto x = dynamic_cast<Base*>(x)) { 
    // read something from \c x now that we know its defined  
} 

请注意,这很好地将x的范围限制在if子句的内部,如果我们使用ifelse if来执行多个连续的dynamic_cast,这通常会更方便。