【问题标题】:Visibility of private field of a template class from a template function模板函数中模板类的私有字段的可见性
【发布时间】:2021-12-01 08:05:27
【问题描述】:

我有一个模板类

template<class T>
class MyClass
{
public:
    MyClass() { privateField = 0; };
    T getPrivateField() {
        return privateField;
    }
private:
    T privateField;
};

还有一个模板函数,它将 MyClass 的实例作为参数

template<class T>
T foo(MyClass<T> mc) {
    return mc.privateField;
}

我很困惑,我可以在模板函数中看到 MyClass 的私有字段,但实际上不能使用它。
Here is an example of field visibility(screenshot)
问题:
为什么我可以在模板函数中准确地看到 MyClass 的私有字段,以及如何在我的代码中禁用它(如果可能的话)?还是就像 Visual Studio 的一个功能?

【问题讨论】:

  • 代码自动完成不是由 C++ 定义的。这只是您的 IDE,向您展示了一个您实际上无法使用的成员。
  • 我拿你的模板专门化template&lt;&gt; class MyClass&lt;int&gt; { public: int privateField; }; - 那么函数模板怎么能假设什么?智能感知只是想提供帮助。
  • 请注意,在您显示的屏幕截图中,IntelliSense确实在“privateField”条目中添加了一个小挂锁图标。
  • @AdrianMole 是的,我意识到我有点不专心

标签: c++ class templates access-modifiers


【解决方案1】:

private 将限制您的代码对成员的访问。

它不会使您的部分代码对可能会观察您所写内容的工具不可见。从个人密码可能是私密的意义上说,它不是私密的。

【讨论】:

    【解决方案2】:

    private 并不意味着它对外界完全隐藏,或者班级之外的任何人都不应该知道它的存在。

    考虑这个例子:

    #include <iostream>
    
    struct foo {
        int x = 0;
    };
    
    struct bar : foo {
        private:
            int x = 0;
    };
    
    int main() {
        bar b;
        b.x = 0;
    }
    

    现在假设,main 是由只知道所涉及类的公共部分的用户编写的。他们将无法理解为什么会收到错误消息:

    <source>: In function 'int main()':
    <source>:15:7: error: 'int bar::x' is private within this context
       15 |     b.x = 0;
          |       ^
    <source>:10:13: note: declared private here
       10 |         int x = 0;
          |             ^
    

    诚然,这是一个虚构的例子,bar 可以被认为是损坏的。关键是,如果您的 IDE 不显示任何私有成员,它不一定会帮您一个忙。它们的存在或不存在可以改变仅针对公共接口编写的代码的含义。

    【讨论】:

    • 到目前为止最好的答案。谢谢
    【解决方案3】:

    不要将可见性访问混淆。

    考虑重载解析的行为方式:

    class X {
        private:
            void f(int value);
        public:
            void f(double value);
    };
    

    如果我们尝试从外部使用 int 调用 X::f():

    int main() { 
        X obj;
        obj.f(1234);
    }
    

    我们仍然得到错误:

    <source>:10:15: error: 'void X::f(int)' is private within this context
            obj.f(1234);
    

    我们绝对不希望 main 调用 X::f(double) 仅仅因为它无法访问 X::f(int) 函数。否则,访问可能会改变程序的运行时含义。

    C++ 会

    • 通过名称查找构建重载集
    • 执行解析以选择最佳匹配项
    • 验证访问权限

    按这个顺序。也就是说,在重载决议完成后检查访问。

    【讨论】:

      猜你喜欢
      • 2019-02-11
      • 2010-09-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-28
      相关资源
      最近更新 更多