模板函数中模板私有字段 class 的可见性
Visibility of private field of a template class from a template function
我有模板class
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?
中的一个功能
private
并不意味着它对外界完全隐藏,或者 class 之外的任何人都不应该知道它的存在。
考虑这个例子:
#include <iostream>
struct foo {
int x = 0;
};
struct bar : foo {
private:
int x = 0;
};
int main() {
bar b;
b.x = 0;
}
现在假设,main
是由一位只知道所涉及的 class 部分的 public 部分的用户编写的。他们将无法理解为什么会收到错误消息:
<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 不显示任何私有成员,则不一定会帮您一个忙。它们的存在或不存在可以改变仅针对 public 接口编写的代码的含义。
private
将限制您的代码对会员的访问权限。
它不会使您的部分代码对可能对您编写的内容进行观察的工具不可见。在个人密码可能是私人的意义上,它不是私人的。
不要混淆 visibility 与 access。
考虑重载解析的行为方式:
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++ 将
- 根据名称查找构建重载集
- 执行解析以选择最佳匹配
- 验证访问权限
按照这个顺序。也就是说,在重载解析完成后检查访问。
我有模板class
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?
private
并不意味着它对外界完全隐藏,或者 class 之外的任何人都不应该知道它的存在。
考虑这个例子:
#include <iostream>
struct foo {
int x = 0;
};
struct bar : foo {
private:
int x = 0;
};
int main() {
bar b;
b.x = 0;
}
现在假设,main
是由一位只知道所涉及的 class 部分的 public 部分的用户编写的。他们将无法理解为什么会收到错误消息:
<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 不显示任何私有成员,则不一定会帮您一个忙。它们的存在或不存在可以改变仅针对 public 接口编写的代码的含义。
private
将限制您的代码对会员的访问权限。
它不会使您的部分代码对可能对您编写的内容进行观察的工具不可见。在个人密码可能是私人的意义上,它不是私人的。
不要混淆 visibility 与 access。
考虑重载解析的行为方式:
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++ 将
- 根据名称查找构建重载集
- 执行解析以选择最佳匹配
- 验证访问权限
按照这个顺序。也就是说,在重载解析完成后检查访问。