通过指向派生类的指针访问派生成员变量

Posted

技术标签:

【中文标题】通过指向派生类的指针访问派生成员变量【英文标题】:accessing derived member variables via pointers to derived class 【发布时间】:2015-10-12 17:08:11 【问题描述】:

我试图理解访问派生对象成员背后的逻辑。我有两个指针:如果我通过指向派生类的指针更改派生类中的变量,我注意到我无法通过指向基类的指针的继承类型访问变量的值。

#include <iostream>
#include <string>

class A
    
    public:
        int x;
    ;

class B : public A
    
    public:
        int y;
    ;

int main()
    
    B* pB = new B;
    A* pA = new B;

    std::cout<<"Changing x via pB to 11"<<std::endl;
    pB->x=11;
    std::cout<<"This is x: " << pB->x<<std::endl;
    std::cout<<"What about this x: " << pA->x<<std::endl<<std::endl;

    std::cout<<"Changing x via pA to 42"<<std::endl;
    pA->x=42;
    std::cout<<"This is my new x: " << pB->x<<std::endl;
    std::cout<<"and what about this x now: " << pA->x;

    delete pA;
    delete pB;
    

输出:

通过 pB 将 x 更改为 11 这是 x:11 这个 x 怎么样:0

通过 pA 将 x 更改为 42 这是我的新 x:11 那么这个 x 现在呢:42

我想知道发生了什么以及为什么 x 有两个不同的值。让我感到困扰的是,例如,当我使用多个列表工作时:一个主列表,其中包含指向我所有对象(比如某个动物类)的指针和一个辅助列表——主列表的子样本,其中包含指向某些对象的指针对象(比如爬虫类:公共动物,公共捕食者)——碰巧我希望通过第二个列表(布尔 is_currently_in_water)修改这些成员的值,我不能以一种直接(而且对我来说很直观)的方式做到这一点.我必须跟踪主列表并首先找出哪个动物对象是爬行动物,以便通过主列表进行必要的更改。

多态性是这样设计的吗?这可能是一个非常基本的问题,因为我刚开始学习 C++,虽然我知道如何克服更改代码的问题,但我首先尝试完全掌握发生了什么,因为上述结果相当令人惊讶。

【问题讨论】:

【参考方案1】:

我想知道发生了什么以及为什么x 有两个不同的值。

解释很简单:你有两个x 值,因为你有两个B 类型的独立对象,通过两个指针pApB 引用,它们完全相互独立。

当您打印pB-&gt;x 时,您将打印x 附加到您首先分配的对象;当您打印pA-X 时,您会打印附加到您第二次分配的对象的x。这两个对象不共享成员变量,所以它们的xs 是相互独立的。

如果您想查看两个不同类型的指针指向同一个对象时的行为,请执行以下操作:

B* pB = new B;
A* pA = pB;

现在pApB 指向同一个对象,因此通过一个指针对x 的任何更改都将通过另一个指针“可见”。当然,现在只有一个分配,您需要删除delete pA(或delete pB,如果您愿意)以避免重复删除同一个对象。

【讨论】:

就是这样!这就是我想要的!非常感谢..我多么愚蠢!我没有注意到我的错误并且我的程序运行良好,直到突然我在查询奇怪的行为!既然你直觉地知道我想要做什么,我会给你投票(尽管你第二个回答).... :-) 顺便说一句。如何使用 shared_ptr 做到这一点?在这里收到奇怪的错误消息。 @user2856452 这是一个非常有趣的问题,SO 有几个很好的答案(1 和 2)。【参考方案2】:

有 2 个不同的值,因为您有 2 个不同的对象:

B* pB = new B;
A* pA = new B;

pA 指向的对象与pB 指向的对象没有任何关系。而且,在第一个

std::cout<<"What about this x: " << pA->x<<std::endl<<std::endl;

您正在读取未初始化的数据,这是未定义的行为。

【讨论】:

这是有道理的。谢谢!我实际上想创建两个指向同一个对象的指针(但指的是不同的基类)这可能吗?【参考方案3】:

您试图从两个不同的对象中读取 x。

如果你想用父指针引用你的对象,你需要定义一个父指针,如下所示

B* pB = new B;
A* pA = pB;

现在如果你从指针 pA 改变 x,它也会在 pB 上改变。

【讨论】:

以上是关于通过指向派生类的指针访问派生成员变量的主要内容,如果未能解决你的问题,请参考以下文章

在 C++ 中将指向基类的指针传递给派生类的成员函数

为啥我可以通过指向派生对象的基类指针访问派生私有成员函数?

基类与派生类的指针和成员函数调用原理

为啥指向基类的派生类指针可以调用派生类成员函数? [复制]

通过指向base,static_cast,crtp,删除模板的指针派生的成员

通过基类指针C++访问派生类的成员