【问题标题】:Compilation error when trying to access an attribute from a local class method尝试从本地类方法访问属性时出现编译错误
【发布时间】:2017-09-12 10:48:39
【问题描述】:

我试图从“内部”(本地)类的方法访问“外部”类的属性,但失败了。

编译失败

class outer
{
    public:
        std::string name;

        class inner
        {
          public:
            void hello();  
        };

        void dostuff();

};

void outer::inner::hello(){std::cout << "Hello " << name << "\n";}

void outer::dostuff(){inner instanceInner; instanceInner.hello();}


int main()
{
   outer instanceOuter;
   instanceOuter.name = std::string("Alice");
   instanceOuter.dostuff();

   return 0;
}

编译错误:

9:21: error: invalid use of non-static data member 'outer::name'
21:53: error: from this location

我真的不希望name 成为一个静态成员,但我并不介意我的特定目的outer 是一个单身人士。所以我尝试了static std::string name; 并得到了

编译错误:

/tmp/ccqVKxC4.o: In function `outer::inner::hello()':
:(.text+0x4b): undefined reference to `outer::name'
/tmp/ccqVKxC4.o: In function `main':
:(.text.startup+0x1f): undefined reference to `outer::name'
collect2: error: ld returned 1 exit status

你能帮帮我吗?

【问题讨论】:

    标签: c++ class compiler-errors local


    【解决方案1】:

    您的问题在于您的hello() 函数。 name 在此处超出范围。它不是您的inner 课程的一部分。不幸的是,您的内部类将无法看到您的外部类及其成员,因此:

    void outer::inner::hello(){
        std::cout << "Hello " << name << "\n";
    }
    

    会产生一个错误,告诉你name 找不到。

    您可以执行以下操作:

    #include <iostream>
    #include <string>
    
    class outer
    {
        public:
            static std::string name;
    
            class inner
            {
              public:
                void hello();  
            };
    
            void dostuff();
    
    };
    
    
    std::string outer::name = ""; // This is key. You need to instantiate outer's name somewhere.
    
    void outer::inner::hello(){std::cout << "Hello " << outer::name << "\n";}
    
    void outer::dostuff(){inner instanceInner; instanceInner.hello();}
    
    
    int main()
    {
       outer instanceOuter;
       instanceOuter.name = std::string("Alice");
       instanceOuter.dostuff();
    
       return 0;
    }
    

    输出:

    Hello Alice
    

    【讨论】:

    • 感谢您的回答。我看不出你的“你好”和我的(void outer::inner::hello(){std::cout &lt;&lt; "Hello " &lt;&lt; name &lt;&lt; "\n";})有什么区别。我有什么误解吗?
    • 我只是指出你的错误所在以及它发生的原因。如果您现在检查我的编辑,您可以看到管理此@Remi.b 的建议
    • 我可以将name 传递给函数。我尽量不通过它。原因是我有一个相对较长的代码(约 1000 行),我只是将整个想法包装在一个外部类中。我希望不必将外部类的每个属性都传递给每个函数调用。请注意,将所有内容作为参数传递最终也可能会降低性能,因为小函数被重复调用,我可能有 5 个参数作为参考传递。否则最终可能无法做到(除非通过外部类的实例调用每个属性)
    【解决方案2】:

    重复(稍作修改)我在另一个答案中提到的内容,similar recent SO question

    C++ 嵌套类不与其外部类共享数据——如果存在 在这种情况下,内部类的每个实例都将位于 与对应的外部实例的一对一关系 类,因此不会添加额外的功能。相反,主要 嵌套类的目的是:

    1. 命名空间含义:outer::innerouter_inner更有意义
    2. 根据 C++ 版本标准,嵌套类对外部类实例的成员对象具有额外的可见性
    3. 也许还有我不知道的其他人

    这是一个关于何时/为什么在 C++ 中使用嵌套类的热门参考问题:Why would one use nested classes in C++?

    在您的情况下,inner 类不能引用数据 name 没有 a) 将访问其 nameouter 类的特定实例,或 b) 静态 nameouter 是通用的。第一个解决方案需要使用outer 类的引用来构造inner 类:

    inner (const outer&amp; _o) : o(_o) {}

    其中oconst outer&amp; 类型的私有成员。然后编写hello函数

    void outer::inner::hello(){std::cout << "Hello " << o.name << "\n";}
    

    或者,如果你想将name设为静态,它是一个未定义的引用,因为你必须放置

    std::string outer::name = "bla";
    

    在某处的编译单元中,否则未定义静态成员。

    但是,无论哪种情况,我都担心您误用了嵌套类。它在您的代码中的用途是什么?为什么必须在外部类和嵌套类之间分离数据和成员函数?你确定一节课不能更好地满足你的目的吗?

    【讨论】:

      猜你喜欢
      • 2012-03-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多