为什么继承的函数会更改基类中的成员变量,而不是同名的对象名称

时间:2018-06-08 10:57:29

标签: c++ oop

我想问为什么setX函数在这里设置类A中的x成员变量而不是类D中的成员变量x,即使我通过D对象调用setX函数? 编译器是如何做到的?

#include<iostream>
using namespace std;

class A
{

public:
    int x;
    A() { cout << "A cons" << endl; }
    void setX(int i){ x = i; cout << "setxA" << endl; }
    void print() { cout << x; }
};

class B : public A
{
public:
    int x =30;
    B() { cout << "B cons" << endl;  }
};



class D : public B {
public:
    D() {
        cout << "D cons" << endl;

    }
    void func() {
        setX(10);
        cout << x << endl;
        cout << B::x << endl;
        cout << A::x << endl;


    }
};

int main()
{
    D d;
    d.func();
    return 0;
}

此代码的输出是 三十 三十 10

2 个答案:

答案 0 :(得分:1)

这称为名称隐藏。 AB都有成员x两个成员始终存在(您无法以相同的方式访问它们)。 A了解其成员x,因此setX函数确切地设置了此成员A::x。在B中,您可以定义另一个隐藏 x的{​​{1}}。这意味着,如果你这样做

A::x

B obj;
obj.x = 10;

您将同时访问D obj; obj.x = 10; (因为B::x在继承层次结构中较低,因此会隐藏B。)

以下是您仍然可以使用不同演员表访问A::x的示例。

A::x

产生输出:

#include <iostream>

struct A {
    int x = 0;
    void setX(int i) { x = i; }
};

struct B : A {
    int x = 20;
};

int main()
{
    B obj;
    A castToA = static_cast<A>(obj);
    A* castToAPtr = reinterpret_cast<A*>(&obj);

    std::cout 
        << "access via B:        " << obj.x << "\n"
        << "access via A:         " << castToA.x << "\n"
        << "access via A*:        " << castToAPtr->x << "\n"
        << "access via B::(A::x): " << obj.A::x << "\n\n";


    obj.setX(100);
    std::cout << "set x to 100\n\n";

    std::cout 
        << "access via B:        " << obj.x << "\n"
        << "access via A:         " << castToA.x << "\n"
        << "access via A*:        " << castToAPtr->x << "\n"
        << "access via B::(A::x): " << obj.A::x << "\n\n";

    return 0;
}

答案 1 :(得分:0)

你的B级有一个x而且A有一个X.因此,你有两个x在B! 那你可以从你的B类中删除x吗?

如果您需要两者,可以使用

访问它们

你已经做过的B方法中的A :: x或B :: x。

所以你的D类也有x和调用setX调用A的setX方法。在D中,你看到B中的x,它隐藏了你的x,A按预期工作。

你的方法A :: setX不知道你以后派生它。如果要覆盖该方法,B已经定义了一个自己的B :: setX,然后也将在D中使用。

如何覆盖方法并访问派生类中的参数的示例:

class A
{
    public:
        int x;    // A::x 
        int y = 40; // A::y

        // this function only knows about A::x
        void setX(int i){ x = i; cout << "setxA" << endl; }
        void setY(int i){ y = i; cout << "setyA" << endl; }
};

class B : public A
{
    public:
        int x =30; // this x ( B::x) hide A::x
        int y =50; // this y hides also A::y

        // now we override setY from A ( hiding setY from A! )
        void setY(int i){ y = i; cout << "setyB" << endl; }

};



class D : public B {
    public:
        void func() {
            setX(10);   // Calls A::setX, as A::setX only knows about
                        // A::x it will access A::x
            cout << "X" << std::endl;
            cout << x << endl;
            cout << B::x << endl;
            cout << A::x << endl;

            setY(90);
            cout << "Y" << std::endl;
            cout << y << endl;
            cout << B::y << endl;
            cout << A::y << endl;
        }
};

int main()
{
    D d;
    d.func();
    return 0;
}