【问题标题】:C++ class template function can access nested class private memberC++类模板函数可以访问嵌套类私有成员
【发布时间】:2018-03-11 03:32:51
【问题描述】:

以下代码无法按预期编译:

#include<iostream>
class Enclosing {
    int x;
    class Nested { int y; };

    void EnclosingFun(Nested *n) {
        std::cout << n->y;  // Compiler Error: y is private in Nested
    }
};

但是,如果我将 EnclosureFun 更改为模板成员函数,编译器 (gcc-7) 不会抱怨访问 y:

#include<iostream>
class Enclosing {      
    int x;
    class Nested { int y; };

    template <typename T>
    void EnclosingFun(Nested *n, T t) {
        std::cout << t << n->y;  // OK? Why?
    }      
};

这是 gcc 中的错误吗?还是c++对模板成员函数访问嵌套类有不同的访问规则?

【问题讨论】:

  • 你从来没有调用过它,这个函数没有被实例化。在 main 中添加调用。
  • @S.M.您应该将其扩展为答案。
  • @RSahu 好的,我将评论扩展到答案。但它已经在我面前得到了回答。

标签: c++ templates private instantiation


【解决方案1】:

这是 gcc 中的错误吗?还是c++对模板成员函数访问嵌套类有不同的访问规则?

也没有。

按照标准,§17.8.1 Implicit instantiation [temp.inst]

实现不应隐式实例化函数模板、变量模板、成员模板、非虚拟成员函数、成员类、类模板的静态数据成员或 constexpr if 语句的子语句 ( [stmt.if]),除非需要这样的实例化。

这意味着,Enclosing::EnclosingFun() 没有在此处实例化。将调用添加到它会导致它被实例化,然后你会得到错误,例如

prog.cc:8:30: error: 'int Enclosing::Nested::y' is private within this context
         std::cout << t << n->y;  // OK? Why?
                           ~~~^

LIVE

【讨论】:

  • 这实际上非常有用。例如,如果我正在编写std::vector&lt;T&gt;,如果T 没有默认构造函数,resize 将不起作用。幸运的是,我可以像T 那样写resize,只要用户不使用resize,代码就会编译
【解决方案2】:

这不是 GCC 中的错误。您不调用函数模板,因此该函数未实例化,并且它不会尝试访问嵌套类的私有成员。尝试在真实函数(不是模板)中的某处调用您的函数或尝试引用它(隐式实例化)。

函数模板本身不是类型、函数或任何其他实体。仅包含模板定义的源文件不会生成任何代码。为了使任何代码出现,必须实例化模板:必须确定模板参数,以便编译器可以生成实际的函数(或类,从类模板)。

当代码在上下文中引用需要函数定义存在的函数,并且该特定函数没有被显式实例化时,就会发生隐式实例化。

template void Enclosing::EnclosingFun(Enclosing::Nested *n, int t); // instantiates the function for the second int parameter

【讨论】:

    猜你喜欢
    • 2021-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-20
    • 2015-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多