当前位置: 首页 > 知识库问答 >
问题:

C++11:为什么私有成员模板可以在类外访问?

越胤
2023-03-14

我只是碰巧发现,可以使用using指令在封闭类之外直接访问嵌套私有模板类:

class wrapper
{
private:
    template <typename T>
    class __tklass {};

    class __klass {};
};

template <typename T>
using tklass = wrapper::__tklass<T>;    // Expected error but compiles OK

// using klass = wrapper::__klass;      // "Error: __klass is private"

int main()
{
    tklass<int> v1;                     // Expected error but compiles OK

    // wrapper::__tklass<int> v3;       // "Error: __tklass is private"
    // wrapper::__klass v4;             // "Error: __klass is private"
}

标记为“error:__xxx is private”的行在未注释时正确报告错误。但是使用tklass的行编译时不会受到编译器的任何抱怨。

我在GCC-4.9.2、Clang-3.5.0和visual studio 2013 Express上尝试了这一点。GCC命令行:

g++ -std=c++11 -pedantic -Wall -Wextra -Wshadow myfile.cpp

共有1个答案

邴烨
2023-03-14

这绝对是一个编译器bug,实际上是一个众所周知的bug:GCC#47346(首次报告于2011年1月)和Clang#15914(首次报告于2013年5月)。您的__tklass显然是private,并且模板别名没有标记为friend,因此这应该是一个简单的访问错误。

最简单的复制来自Clang示例附件,该版本在gcc 4.9.2和Clang 3.5.0上都编译,但肯定不应该在两者上编译

class A
{
  class B {};
};

template<typename>
using T = A::B;

T<void> t;

然而,在这方面,Clang严格来说比GCC好,因为这个特殊的bug似乎只出现在模板别名中。一个“变通方法”(如果您需要这样的东西来处理编译器不正确地允许的情况...)将恢复到C++11之前的模板别名:

template <typename>
struct T {
    using type = A::B;
};

T<void>::type t;

该代码不能正确地用clang编译(错误:'B'是'a'的私有成员),但仍然可以用GCC编译。

 类似资料:
  • 问题内容: 我观察到外部类可以访问内部类的私有实例变量。这怎么可能?这是演示相同代码的示例代码: 为什么允许这种行为? 问题答案: 内部类只是一种将真正属于原始外部类的功能完全分开的方法。当你有两个要求时,可以使用它们: 如果是在单独的类中实现的,那么外部类中的某些功能将最为清晰。 即使在单独的类中,该功能也与外部类的工作方式紧密相关。 鉴于这些要求,内部类可以完全访问其外部类。由于它们基本上是外

  • 问题内容: 谁能告诉我私人会员的访问级别?我一直对这段代码感到困惑:为什么可以在外部类的“打印”方法中访问Line类的私有成员k? 问题答案: 规则在有关可访问性的JLS章中 否则,如果声明了成员或构造函数,则仅当访问发生 在封装成员或构造函数的声明的顶级类(第7.6节)的主体内 时,才允许访问 。 在这里,成员字段在类中声明。当您在方法中访问它时,您正在 包含该 成员 的声明的顶级类的主体中对其

  • 问题内容: 我正在研究TypeScript中私有成员的实现,但我感到有些困惑。Intellisense不允许访问私有成员,但是在纯JavaScript中,仅此而已。这使我认为TS无法正确实现私有成员。有什么想法吗? 问题答案: 就像类型检查一样,成员的隐私仅在编译器中强制执行。 私有属性被实现为常规属性,并且不允许类外的代码对其进行访问。 为了使某些东西真正成为类的私有对象,它不能成为该类的成员,

  • 我很难弄清楚如何使用适当的模板化参数调用setValue函数。在ParameterBase抽象基类中不可能有模板化的参数。非常感谢任何帮助。 附注。我没有使用boost::any的灵活性。

  • 问题内容: 是在类级别还是在对象级别的私有成员访问权限。如果是在对象级别,则以下代码不应编译 请说明在sub的messWithI()方法中访问obj的成员i是否有效 问题答案: 正如DevSolar所说的,它处于(顶级)类级别。 从Java语言规范的6.6节开始: 否则,如果将成员或构造函数声明为私有,则仅当访问发生在包含成员或构造函数的声明的顶级类(第7.6节)的主体内时,才允许访问。 请注意,

  • 问题内容: 在Java中,内部类可以访问封闭类的私有成员。但是外层可以访问内层的私有成员吗?这与内部类是否静态无关。我认为这是不正确的,但是以下代码似乎可以编译并正常工作。 问题答案: 是的,没关系。从JLS,第6.6.1节中: 否则,如果声明了成员或构造函数,则仅当访问发生在封装成员或构造函数的声明的顶级类(第7.6节)的主体内时,才允许访问。 您甚至可以在另一个嵌套类型Y中引用嵌套类型X的私有