【问题标题】:Derived Classes Cannot Access Private Members派生类不能访问私有成员
【发布时间】:2018-04-19 07:04:17
【问题描述】:

在 C++ 中:
这个概念是派生类对象和成员函数不能访问父类的私有成员。但是,如果父类的公共成员函数返回私有变量的引用,并且父类在子类中是公开继承的,并且子类有一个从父类调用该函数的函数(在本例中为 display()),该怎么办?类(在本例中为 show())并获取私有变量 x 的引用。 a 的地址应该匹配 x 但我不知道为什么它不同?

enter code here

#include <iostream>

using namespace std;
class test{
    int x=10;
    public:
    int & show();
};
class ChildTest: public test{
    public:
    void display(){
        int a=show();
        cout<<&a<<endl;
    }
};
int & test::show(){
    cout<<&x<<endl; //so this address should match the above address but it //is not matching I don't understand why?
    return x;
}
int main()
{
    ChildTest obj;
    obj.display();
    return 0;
}

输出:
0x7ffe5b751bb0
0x7ffe5b751bb4

鉴于我正在传递对私有变量的引用,我不明白地址更改背后的概念是什么。

【问题讨论】:

    标签: c++ inheritance reference


    【解决方案1】:

    整数是一个值。例如,如果您使用自定义类而不是整数,您将获得相同的地址。但是,作为一种值类型,所有 Integer 变量在内存中都有自己独立的空间。要拥有相同的地址,您的变量 a 应更改为指向整数值的指针:

        void display() {
            int* a=show();
            cout<<a<<endl;
        }
    

    通过该更改,地址应该相同。请注意,我删除了输出中的&amp;。那是因为变量a 现在指向值的地址。要使用该值,请使用*a 调用。

    来源(https://www.cprogramming.com/tutorial/lesson6.html):

    指向某物:检索地址

    为了让一个指针真正指向另一个变量,它是 还必须具有该变量的内存地址。要获得 变量的内存地址(它在内存中的位置),放 & 符号 在变量名前面。这使它给出了它的地址。这是 称为地址运算符,因为它返回内存地址。 方便的是,& 和 address-of 都以 a 开头;那是一个 记住您使用 & 获取地址的有用方法 多变的。

    例如:

       #include <iostream>
    
       using namespace std;
    
       int main() {
           int x;    // A normal integer   
           int *p;   // A pointer to an integer
    
           p = &x;           // Read it, "assign the address of x to p"   
           cin>>x;          // Put a value in x, we could also use *p here  
           cin.ignore();   
           cout<< *p <<"\n"; // Note the use of the * to get the value  
           cin.get(); 
       }
    

    编辑:有一个错误,我写这篇文章时有人回答了。

    【讨论】:

    • 你还有一个*a。 :-)
    • 其实我稍后会更新一个关于如何使用指针的来源。
    【解决方案2】:

    当你写作时

    int a = show();
    

    您是说“创建一个名为a 的全新整数变量,并使用show() 的返回值对其进行初始化。即使show 返回int &amp;,因为您已经明确说过“我'd like a new int," C++ 创建一个存储在 int 中的值的副本,由 show() 的返回引用。

    要解决此问题,请将您的代码更改为阅读

    int& a = show();
    

    这表示“创建一个新的int 引用并将其绑定到show() 返回的引用所指的任何内容。”这样一来,就不会复制整数,而且您应该会看到相同的地址

    请注意,这与继承无关。这纯粹是复制int 与存储引用的功能。

    【讨论】:

    • 如果show() 不返回引用会怎样?
    • @Omnifarious Hoo boy,如果你存储了一个非const 引用,那么你就有麻烦了,因为你有一个悬空引用。但是,话又说回来,我认为 OP 在这种情况下看到不同的地址会感到惊讶,因为他们已明确选择返回原始值的副本。
    • 实际上,不,display() 可以正常运行,并且保证在show() 返回int(不是int &amp;)的情况下运行正常。现在,如果 display 试图返回它的引用,那就是麻烦开始的地方。如果您显式创建对临时对象的命名引用,则可以保证该临时对象在该名称的整个生命周期内都存在。试着帮助你改进你的答案。 :-)
    • @Omnifarious 我想我在这里遗漏了一些东西。我认为 OP 担心的是display 中打印的地址与show 中打印的地址不匹配。如果show 按值返回其结果,那么display 将不得不打印出与show 不匹配的地址,因为它显示的int 是不同的int 值。不过,也许我误解了你的暗示。
    • 您很好地回答了 OP 的问题。我在想你已经用一种关于将引用绑定到返回值的方式来表达关于 show 的返回值的一句话。但是在重新阅读时我错了。
    【解决方案3】:

    这里只显示局部变量a的地址(其值为test::x

    更改为int&amp; a=show(); 以显示相同的地址。

    【讨论】:

    • 谢谢@Jarod42。所以通过这种方式,我们可以访问和更改任何类的私有变量。即使变量是私有的,对吗?
    • @amitpandey - 是的。 private 关键字仅影响名称的可访问性。它对名称所指的存储没有影响。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-08-07
    • 1970-01-01
    • 1970-01-01
    • 2021-07-01
    • 1970-01-01
    • 2011-08-04
    • 1970-01-01
    相关资源
    最近更新 更多