内部类可以访问私有变量吗?


116
class Outer {

    class Inner {
    public:
        Inner() {}
        void func() ;
    };

private:
    static const char* const MYCONST;
    int var;
};

void Outer::Inner::func() {
    var = 1;
}

const char* const Outer::MYCONST = "myconst";

当我使用类Outer :: Inner'进行编译时,这没有错误,而没有名为`var'的成员

Answers:


120

内部类是它所定义的类的朋友。
所以,是的;类型的对象Outer::Inner可以访问成员变量var类型的对象的Outer

但是与Java不同,类型Outer::Inner的对象和父类的对象之间没有关联。您必须手动建立父子关系。

#include <string>
#include <iostream>

class Outer
{
    class Inner
    {
        public:
            Inner(Outer& x): parent(x) {}
            void func()
            {
                std::string a = "myconst1";
                std::cout << parent.var << std::endl;

                if (a == MYCONST)
                {   std::cout << "string same" << std::endl;
                }
                else
                {   std::cout << "string not same" << std::endl;
                }
            }
        private:
            Outer&  parent;
    };

    public:
        Outer()
            :i(*this)
            ,var(4)
        {}
        Outer(Outer& other)
            :i(other)
            ,var(22)
        {}
        void func()
        {
            i.func();
        }
    private:
        static const char* const MYCONST;
        Inner i;
        int var;
};

const char* const Outer::MYCONST = "myconst";

int main()
{

    Outer           o1;
    Outer           o2(o1);
    o1.func();
    o2.func();
}

14
从技术上讲,在当前的C ++标准中,嵌套类没有对其封闭类的特殊访问权。参见标准的第11.8.1节。但是也可以看到此标准缺陷:open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#45
Greg Rogers 2009年

1
就其价值而言,GCC遵循那里给出的建议解决方案,其他编译器也可能这样做。
格雷格·罗杰斯

24
现在,C + 11标准符合上述说明。
马丁·约克

1
在Java中,首次访问内部类时,会向非静态内部类隐式为其外部类的实例提供引用(指针)。换一个说法,jvm正在为您隐式编写一个代码,类似于@LokiAstari在其答案中向我们显示的代码。这是摘自Effective Java 2nd Ed: “第22项:在非静态成员上偏爱静态成员类”:“如果省略此修饰符(在声明内部类时使用static关键字),则每个实例将对其封闭的实例进行无关的引用”。
David Lee

3
@Loki Astari:我读了最后一句“您必须手动建立父子关系”,并解释了随后的代码片段,作为如何正确执行此操作的示例!
布伦特·巴卡拉

31

内部类可以访问外部类的所有成员,但是它没有对父类实例的隐式引用(不同于Java的某些怪异)。因此,如果将对外部类的引用传递给内部类,则它可以引用外部类实例中的任何内容。


7
这从c ++ 11起是正确的
thrantir

6

属于 Outer的任何内容均应有权访问Outer的所有公共或私人成员。

编辑:您的编译器是正确的,var不是Inner的成员。但是,如果您有对Outer实例的引用或指针,则它可以访问该实例。


2

var不是内部类的成员。

要访问var,应使用指向外部类实例的指针或引用。例如,如果内部类是外部的朋友,则pOuter-> var将起作用,或者,如果严格遵循C ++标准,则var是公共的。

有些编译器将内部类视为外部类的朋友,但有些可能不会。请参阅此文档以了解IBM编译器

“一个嵌套类在另一个类的范围内声明。一个嵌套类的名称是其所在类的本地名称。除非使用显式指针,引用或对象名,否则嵌套类中的声明只能使用可见的构造,包括类型名称,静态成员和来自封闭类和全局变量的枚举数。

嵌套类的成员函数遵循常规的访问规则,并且对其封闭类的成员没有特殊的访问特权。封闭类的成员函数对嵌套类的成员没有特殊的访问权限。”


4
错误。查看其他答案-3年之前。“如果严格遵循C ++标准”,他们将得出与您不同的答案。从C ++ 11的早期草案开始,嵌套类可以通过引用/指针访问父级的所有成员。无需明确声明friendpublic。过去,谁在乎IBM是否错了/过时了?此答案在发布前三年已经过时了。
underscore_d

1

首先,您正在尝试访问varC ++不允许的类之外的非静态成员。

马克的答案是正确的。

属于Outer的任何内容均应有权访问Outer的所有公共或私人成员。

因此,您可以做两件事,要么声明var为as ,要么static使用外部类实例的引用来访问“ var”(因为朋友类或函数也需要引用来访问私有数据)。

静态变量

更改varstatic如果不想var与该类的实例相关联。

#include <iostream>

class Outer {

private:
    static const char* const MYCONST;
    static int var;

public:
   class Inner {
    public:
        Inner() {
          Outer::var = 1;
        }
        void func() ;
    };
};

int Outer::var = 0;

void Outer::Inner::func() {
    std::cout << "var: "<< Outer::var;
}

int main() {
  Outer outer;
  Outer::Inner inner;
  inner.func();

}

输出-var:1

非静态变量

对象的引用必须访问任何非静态成员变量。

#include <iostream>

class Outer {

private:
    static const char* const MYCONST;
    int var;

public:
   class Inner {
    public:
        Inner(Outer &outer) {
          outer.var = 1;
        }
        void func(const Outer &outer) ;
    };
};

void Outer::Inner::func(const Outer &outer) {
    std::cout << "var: "<< outer.var;
}

int main() {
  Outer outer;
  Outer::Inner inner(outer);
  inner.func(outer);

}

输出-var:1

编辑-外部链接是指向我的博客的链接。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.