继承:为什么继承变量和提供变量之间的行为存在差异?

时间:2012-03-12 10:31:46

标签: c++ inheritance

例如,在这段代码中,如果注释掉line [a],则输出为0.

  

inh2.cpp

#include<iostream>
using namespace std;

class A {
    public:
        int x;
        A() { x = 10; }
};

class B : public A {
    public:
        int x;  // <--------- [a]
        B() { x = 0; }
};

int main() {
    A* ab = new B;
    cout << ab->x << endl;
}
  

来自gcc的结果

$ g++ inh2.cpp
$ ./a.out
10
$

我有两个问题:

  1. 在上述情况下,ab->x如何解析为10?该对象的类型为class B,因此应该为0
  2. 为什么评论Line [a]会改变代码的行为?我的理由是,x无论如何都会被继承,这应该导致相同的行为。

  3. 我对上述问题1的推理:

    • ab指向class B对象的内存位置。在某种意义上,它是一个物理对象,所有带有值的变量都被分配了内存。

    • 此对象中的变量x存储值0

    • ab->x完成时,ab告诉我们对象的内存位置,然后我们在里面查看x是0.所以我们应该打印0。

    我在哪里错了?

2 个答案:

答案 0 :(得分:3)

  1. 是的,它的类型为B,但是您将其指定为指向A的指针,因此它使用在A上定义的x(如当我们处理指向A的指针时,我们不知道B甚至存在,即使这是你分配的内容。

  2. 当您注释掉该行时,在构建阶段,首先调用A构造函数,然后调用B构造函数,它设置x(在其基类中)此时只有一个x,最后调用Bs构造函数。

答案 1 :(得分:1)

进行一些小修改:

#include <iostream>

using namespace std;

class A {
public:
    int x;
    A()
        :x(10)
    {
        std::cout << __FUNCTION__ << std::endl;
        std::cout << x << std::endl;
    }
    virtual ~A() {}
};

class B : public A {
public:
    int x;  // <--------- [a]
    B()
        :A()
        ,x(0)
    {
        std::cout << __FUNCTION__ << std::endl;
        std::cout << x << std::endl;
    }
};

int main() {
    A* ab = new B;
    cout << "ab->x: " << ab->x << endl;
    cout << "ab->A::x " << ab->A::x << endl;

    B* b = dynamic_cast<B*>(ab);
    cout << "b->x: " << b->x << endl;
    cout << "b->A::x " << b->A::x << endl;
    cout << "b->B::x " << b->B::x << endl;
}

这会给你:

A
10
B
0
ab->x: 10
ab->A::x 10
b->x: 0
b->A::x 10
b->B::x 0

这表明:

  • ab->x引用A::x,因为ab的类型为A*,并且没有virtual变量。如果你想要多态,你将不得不写一个virtual int get_x() const方法。
  • B::x隐藏A::x。这是一个坏主意,应该避免。考虑为成员变量使用更有意义的名称,并确定在引入新变量之前是否可以重用基类的变量。
  • 通过转换为B*,您可以访问B个成员以及A个成员。这应该是不言自明的。