【问题标题】:Can inner classes access private variables?内部类可以访问私有变量吗?
【发布时间】:2010-10-03 22:05:13
【问题描述】:
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' 的成员

【问题讨论】:

    标签: c++ inner-classes


    【解决方案1】:

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

    虽然与 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();
    }
    

    【讨论】:

    • 从技术上讲,在当前的 C++ 标准中,嵌套类没有对其封闭类的特殊访问权限。见标准第 11.8.1 节。但是,请参阅此标准缺陷:open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#45
    • 对于它的价值,GCC 遵循那里给出的建议解决方案,其他编译器可能也这样做。
    • C+11 标准现在符合上述说明。
    • 在 Java 中,当第一次访问内部类时,非静态内部类会隐式地为其外部类的实例提供一个引用(指针)。换个说法,jvm 隐含地为您编写代码,类似于@LokiAstari 在他的回答中向我们展示的代码。这是Effective Java 2nd Ed“Item 22: Favor static member classes over nonstatic”的摘录:“如果你省略这个修饰符(声明内部类时的static关键字),每个实例都会有一个对其封闭实例的无关引用”。
    • @Loki Astari:我读了最后一句“你必须手动建立父子关系”,并将后面的代码片段解释为如何正确地做到这一点!
    【解决方案2】:

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

    【讨论】:

    • 这在 c++11 中是正确的
    【解决方案3】:

    任何属于 Outer 的一部分的东西都应该可以访问 Outer 的所有公共或私人成员。

    编辑:你的编译器是正确的,var 不是 Inner 的成员。但如果你有一个指向 Outer 实例的引用或指针,它就可以访问它。

    【讨论】:

      【解决方案4】:

      首先,您尝试在 C++ 中不允许的类之外访问非静态成员 var

      马克的回答是正确的。

      任何属于 Outer 一部分的东西都应该可以访问 Outer 的所有成员,无论是公共的还是私人的。

      所以你可以做两件事,要么将var 声明为static,要么使用外部类实例的引用来访问'var'(因为friend class or function 也需要引用才能访问私有数据)。

      静态变量

      如果您不希望 var 与类的实例相关联,请将 var 更改为 static

      #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();
      
      }
      

      输出变量: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);
      
      }
      

      输出变量:1

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

      【讨论】:

        【解决方案5】:

        var 不是内部类的成员。

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

        一些编译器将内部类视为外部类的朋友,但有些可能不会。见this document for IBM compiler

        "一个嵌套类是在另一个类的作用域内声明的。一个嵌套类的名字对于它的封闭类来说是局部的。除非你使用显式的指针、引用或对象名,否则嵌套类中的声明只能使用可见的构造,包括类型名称、静态成员和来自封闭类和全局变量的枚举数。

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

        【讨论】:

        • 错了。查看其他答案 - 3 年前。 “如果严格遵循 C++ 标准”,他们会得到与您不同的答案。在 C++11 的早期草案中,嵌套类可以通过引用/指针访问父级的 所有 成员。不需要显式声明friendpublic。谁在乎 IBM 过去是否错误/过时,是否存在死链接?这个答案在发布前 3 年就已经过时了。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-02-14
        • 2013-09-20
        • 1970-01-01
        • 1970-01-01
        • 2014-09-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多