繁体   English   中英

从基类指针访问派生类成员

[英]Accessing derived class member from base class pointer

我真的很困惑。 我遇到了以下情况,其中C继承自A和B,但是根据事物的分配方式,我会得到不同的行为:

  • 如果我newC实例,并将其存储在A指针,然后分配给它的值设置为B指针,并调用的方法, AA指针,而方法BB指针,我得到奇怪的事情。 ..(请参阅测试1 )。

  • 如果我newC实例,并将其存储在一个C指针,然后分配给它的价值的AB指针,并调用的方法, AA指针,而方法BB指针,我得到了什么我希望...(请参阅测试2 )。

我的问题是: 为什么测试1的行为方式如此?

A级

class A
{
public:
    A() { aMember = 'A'; }
    virtual ~A() {}
    virtual char getAMember() { return aMember; }
private:
    char aMember;
};

B级

class B
{
public:
    B() { bMember = 'B'; }
    virtual ~B() {}
    virtual char getBMember() { return bMember; }
private:
    char bMember;
};

C级

class C : public A, public B
{
public:
    C() : A(), B() {}
    virtual ~C() {}
};

具有Test1和Test2的主体

#include <cstdio>

int main(void)
{
    C* c;
    A* a;
    B* b;

    printf("Test 1\n");

    a = new C();
    b = (B*)a;

    printf("a->getAMember(): %c\n",a->getAMember()); // prints A
    printf("b->getBMember(): %c\n",b->getBMember()); // prints A ?!

    printf("Test 2\n");

    c = new C();
    a = c;
    b = c;

    printf("a->getAMember(): %c\n",a->getAMember()); // prints A
    printf("b->getBMember(): %c\n",b->getBMember()); // prints B

    return 0;
}

您使用的是邪恶的C样式强制转换,在这种情况下,等效于reinterpret_cast 这会将A子对象的地址重新解释为B子对象的地址,后者实际上在另一个地址处; 强制类型转换无效,如果您尝试通过该指针访问B ,则会产生不确定的行为。

使用dynamic_cast在同一完整对象的多态基类子对象之间安全地交叉转换(记住,如果要转换指针,则要检查结果); static_cast到派生类(在本例中为C* ),如果您完全确定要指向该类型的对象。

在第二种情况下,您正在安全地从派生类转换为基类,因此所有内容都定义良好,无需任何强制转换。

这是因为此强制转换b = (B*)a; 导致未定义的行为。 这样的转换会强制a的类型。 您应该使用dynamic_cast。

a = new C();
b = dynamic_cast<B*>(a);

由于您的虚函数,这将允许运行时实际检查a的类型,并产生正确的结果。 如果强制转换不是正确的强制转换,则将导致为nullptr

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM