为什么 C++ 模板类可以访问其基类的私有成员?

简·海蒂奇

使用 Visual Studio 2019 (v 16.7.3),我发现模板类可以访问它的非模板基类的私有成员。这是预期的行为还是编译器错误?

当派生类不是模板类时,基类的私有成员按预期无法访问:

class A
{
};

class Base
{
public:
    Base() : m_pA(new A()) {}
private:
    A* m_pA;
};

class Derived :
    public Base
{
public:
    Derived() : Base() {}
    A* get_a() { return m_pA; }  // 'Base::m_pA': cannot access private member declared in class 'Base' 
};

int main()
{
    Derived d;
}

== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==

但是,如果我将 Derived 设为模板类,它会毫无怨言地编译:

template<class T>
class Derived :
    public Base
{
public:
    Derived() : Base() {}
    A* get_a() { return m_pA; }
};

int main()
{
    Derived<int> d;
}

== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==
dxiv

发布的代码不会调用,Derived<int>::get_a()因此模板成员函数不会被实例化(并且没有私有父成员的访问”可言)。

添加以下get_a()调用会导致与非模板情况相同的错误。

{
    Derived<int> d;
    d.get_a();  // error: 'A* Base::m_pA' is private within this context
}

[编辑] 模板成员函数的隐式实例化(仅)在使用时在 C++ 标准中规定在temp.inst/4 下

除非模板化类的成员是声明的特 化, 否则当在需要成员定义存在的上下文中引用特化时,或者如果成员定义的存在影响了成员的语义,则该成员的特化将被隐式实例化。程序;

模板特化的显式定义(尽管不仅仅是声明)将导致所有成员的完全实例化,从而导致相同的错误。

extern template class Derived<int>; // explicit declaration - ok

template class Derived<int>;        // explicit definition - error: 'A* Base::m_pA' is private within this context

[编辑 #2 ] 在评论中提出的论点(感谢@Jarod42)认为给定的代码属于“格式错误,不需要诊断”类别,这意味着允许编译器(尽管不是必需的)基于理由拒绝它即使从未使用过成员函数,也不会Derived<T>因为private成员访问而存在类模板的可能(完整)实例化get_a()

此解释基于temp.res.general/6.1的以下部分

程序 格式错误,无需诊断如果:

  • 无法 为模板或 constexpr if 语句的子语句生成 有效的特化,如果模板中的语句未实例化,或者 [...]
  • 如果“可以生成有效的专业化”被认为是整个模板类的完整显式专业化,那么给定的代码片段确实是“格式错误的 NDR ”。

  • 但是,如果“有效专业化”被理解为涵盖模板类的隐式专业化,其中(仅)前面引用的temp.inst/4 中定义的必需成员,则给定的代码片段不属于“格式错误的NDR” “因为get_a()永远不会被实例化(根据temp.inst/11:”一个实现 不应隐式实例化 一个函数模板、一个变量模板、一个成员模板、 一个非虚拟成员函数一个成员类或模板化类的静态数据成员,或 constexpr if 语句的子语句, 除非需要这样的实例化")。

链接的演示显示gcc采用后一种解释,而clang前者。

在任何一种情况下,答案都是,如果模板没有因为 no-valid-specializations-can-exist 子句而被预先拒绝为“格式错误的NDR ”,那么只要 get_a()没有被实例化,它就会编译并正常工作,要么通过直接引用隐式,要么通过模板类的显式特化。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

C ++ | 派生类正在访问基类的私有成员,而不是其自己的私有成员

来自分类Dev

C ++类模板函数可以访问嵌套类的私有成员

来自分类Dev

C ++-访问基类的受保护/私有成员

来自分类Dev

C ++朋友类可以访问其基类的所有成员吗?

来自分类Dev

成为私有成员(c ++类)意味着什么?

来自分类Java

为什么嵌套类的私有成员可以被封闭类的方法访问?

来自分类Java

为什么子类可以通过内部类访问超类的私有成员?

来自分类Java

为什么外部Java类可以访问内部类的私有成员?

来自分类Dev

为什么派生类的私有虚拟成员函数可以从基类访问

来自分类Dev

如何启用朋友类的朋友功能直接在C ++中访问其私有成员

来自分类Dev

为什么Visual Studio允许我在模板函数(C ++)中使用私有成员?

来自分类Dev

为什么C ++允许返回对私有成员的引用

来自分类Dev

为什么在重载C ++时无法访问私有成员

来自分类Dev

访问派生类C ++的私有成员

来自分类Dev

无法从C ++中的类内部访问私有成员?

来自分类Dev

嵌套类时为什么不能从内部类访问外部类的私有成员?

来自分类Dev

为什么 Friend 函数不能访问类的私有成员

来自分类Dev

为什么甚至可以更改私有成员或使用反射在C#中运行私有方法?

来自分类Dev

c++派生类对象没有成员,为什么?

来自分类Dev

在C ++中,类仅包含(默认情况下)私有成员有什么用?

来自分类Dev

重写派生类C ++中基类私有成员的行为

来自分类Dev

无法使用派生类访问类的私有成员的 C++ 代码

来自分类Dev

c ++模板模板:无法访问私有成员

来自分类Dev

使公共成员变量访问C ++中同一类的私有成员

来自分类Dev

为什么私有基类的成员模板无法通过using声明引入?

来自分类Java

为什么嵌套子类访问他们的父类的私有成员,但孙子却不能?

来自分类Java

为什么嵌套子类访问他们的父类的私有成员,但孙子却不能?

来自分类Dev

为什么C ++禁止私有继承final类?

来自分类Dev

在 C++ 中实现复制控制时如何处理基类的私有成员?

Related 相关文章

  1. 1

    C ++ | 派生类正在访问基类的私有成员,而不是其自己的私有成员

  2. 2

    C ++类模板函数可以访问嵌套类的私有成员

  3. 3

    C ++-访问基类的受保护/私有成员

  4. 4

    C ++朋友类可以访问其基类的所有成员吗?

  5. 5

    成为私有成员(c ++类)意味着什么?

  6. 6

    为什么嵌套类的私有成员可以被封闭类的方法访问?

  7. 7

    为什么子类可以通过内部类访问超类的私有成员?

  8. 8

    为什么外部Java类可以访问内部类的私有成员?

  9. 9

    为什么派生类的私有虚拟成员函数可以从基类访问

  10. 10

    如何启用朋友类的朋友功能直接在C ++中访问其私有成员

  11. 11

    为什么Visual Studio允许我在模板函数(C ++)中使用私有成员?

  12. 12

    为什么C ++允许返回对私有成员的引用

  13. 13

    为什么在重载C ++时无法访问私有成员

  14. 14

    访问派生类C ++的私有成员

  15. 15

    无法从C ++中的类内部访问私有成员?

  16. 16

    嵌套类时为什么不能从内部类访问外部类的私有成员?

  17. 17

    为什么 Friend 函数不能访问类的私有成员

  18. 18

    为什么甚至可以更改私有成员或使用反射在C#中运行私有方法?

  19. 19

    c++派生类对象没有成员,为什么?

  20. 20

    在C ++中,类仅包含(默认情况下)私有成员有什么用?

  21. 21

    重写派生类C ++中基类私有成员的行为

  22. 22

    无法使用派生类访问类的私有成员的 C++ 代码

  23. 23

    c ++模板模板:无法访问私有成员

  24. 24

    使公共成员变量访问C ++中同一类的私有成员

  25. 25

    为什么私有基类的成员模板无法通过using声明引入?

  26. 26

    为什么嵌套子类访问他们的父类的私有成员,但孙子却不能?

  27. 27

    为什么嵌套子类访问他们的父类的私有成员,但孙子却不能?

  28. 28

    为什么C ++禁止私有继承final类?

  29. 29

    在 C++ 中实现复制控制时如何处理基类的私有成员?

热门标签

归档