如何限制对静态 public 成员的访问?
How to restrict access to static public members?
#include <cstdio>
struct Settings
{
int i1, i2;
Settings(int i1, int i2) : i1(i1), i2(i2) {}
struct GeneralSettings
{
int gi1, gi2;
} static gs;
void do_something() const
{
printf("%d %d %d %d\n", i1, i2, gs.gi1, gs.gi2);
}
};
Settings::GeneralSettings Settings::gs;
int main()
{
Settings s1(0,1);
Settings s2(1,0);
s1.gs.gi1 = 1; // I would like to access GeneralSettings like this only!
Settings::gs.gi2 = 1; // Can i prevent global access like this?
s2.do_something();
return 0;
}
请参阅上面的代码和评论。除了用 accessors/mutators 制作 Settings::gs
private
之外,还有其他方法可以限制对 Settings::gs
的访问,以便只能通过 Settings
对象访问吗?事实上,任何函数都可以访问 Settings::gs
,无论它是否可以访问 Settings
对象。 Settings::gs
本质上是一个全局对象。
Besides making Settings::gs
private
with accessors/mutators, are there other ways to restrict access to Settings::gs
so that it can be accessed through Settings
objects only?
不是真的(假设你想在 "accessed through" 时进行控制),这几乎就是 private
的要点以及访问器的用途;那就是为实例和私有静态数据提供对内部结构(可能已检查)的访问。
您可以改变语法以获得所需的语义(指针、引用、const 和非常量),但最终一旦成员变量是 public(或通过 public 成员访问,例如指针或引用),您放弃了一定程度的控制。这里的控制是在函数中实现的,是成员函数还是外部的utility/helper函数。
我不确定这里的意图。这取决于你所说的 "accessed through".
是什么意思
如果它正是您所追求的语法, 提供了解决方案。
如果控制力更强,您可以探索创建一个提供自定义 operator*()
和 operator->()
的实用程序 class 的可行性,这样您就可以 "mimic"智能指针(在没有 "smart reference" 的情况下)。我不确定这是否会提供您想要的语法。
您也可以探索 pimpl pattern/idiom (an opaque pointer),它没有回答问题,但提供了一种替代设计,可以更好地解决您遇到的问题。
我仍然不明白这样做的意义,但您可以使用 public 对私有静态成员的引用(顺便说一句,我不建议这样做):
struct A {
private:
struct B { int x, y; } static _b;
public:
// c++11 initialization, prior you need to initialize b in the
// constructor of A
B &b{_b};
};
A::B A::_b{0, 0};
然后:
int main() {
A a1, a2;
std::cout << a2.b.x << " ";
a1.b.x = 4;
std::cout << a2.b.x << std::endl;
}
输出:
0 4
正如@Niall 在评论中指出的那样,将引用作为属性将删除默认赋值运算符:
A a1, a2;
a2 = a1; // copy assignment is implicitly deleted
但是如果您需要它,您可以随时创建自己的,因为您不需要更新 b
:
struct A {
private:
struct B { int x, y; } static _b;
public:
B &b{_b};
A& operator= (A const&) {
// ok, no need to update this->b!
return *this;
}
};
A a1, a2;
a1 = a2; // ok
不过,我可以想到几个选项,就像所有单例一样,这些选项不是线程安全的:
- 您可以只使用
public
reference 来避免 accessors/mutators:
struct Settings {
private:
struct GeneralSettings {
int gi1, gi2;
} static _gs;
public:
int i1, i2;
GeneralSettings& gs;
Settings(int i1, int i2) : i1(i1), i2(i2), gs(_gs) {}
void do_something() const {
printf("%d %d %d %d\n", i1, i2, gs.gi1, gs.gi2);
}
};
- 你实际上可以 make it a full on singleton,尽管这需要一个访问器,而不是一个修改器,并且它会花费你
const
:
struct Settings {
struct GeneralSettings {
int gi1, gi2;
};
GeneralSettings& gs() {
static GeneralSettings gs;
return gs;
}
int i1, i2;
Settings(int i1, int i2) : i1(i1), i2(i2) {}
void do_something() {
printf("%d %d %d %d\n", i1, i2, gs().gi1, gs().gi2);
}
};
#include <cstdio>
struct Settings
{
int i1, i2;
Settings(int i1, int i2) : i1(i1), i2(i2) {}
struct GeneralSettings
{
int gi1, gi2;
} static gs;
void do_something() const
{
printf("%d %d %d %d\n", i1, i2, gs.gi1, gs.gi2);
}
};
Settings::GeneralSettings Settings::gs;
int main()
{
Settings s1(0,1);
Settings s2(1,0);
s1.gs.gi1 = 1; // I would like to access GeneralSettings like this only!
Settings::gs.gi2 = 1; // Can i prevent global access like this?
s2.do_something();
return 0;
}
请参阅上面的代码和评论。除了用 accessors/mutators 制作 Settings::gs
private
之外,还有其他方法可以限制对 Settings::gs
的访问,以便只能通过 Settings
对象访问吗?事实上,任何函数都可以访问 Settings::gs
,无论它是否可以访问 Settings
对象。 Settings::gs
本质上是一个全局对象。
Besides making
Settings::gs
private
with accessors/mutators, are there other ways to restrict access toSettings::gs
so that it can be accessed throughSettings
objects only?
不是真的(假设你想在 "accessed through" 时进行控制),这几乎就是 private
的要点以及访问器的用途;那就是为实例和私有静态数据提供对内部结构(可能已检查)的访问。
您可以改变语法以获得所需的语义(指针、引用、const 和非常量),但最终一旦成员变量是 public(或通过 public 成员访问,例如指针或引用),您放弃了一定程度的控制。这里的控制是在函数中实现的,是成员函数还是外部的utility/helper函数。
我不确定这里的意图。这取决于你所说的 "accessed through".
是什么意思如果它正是您所追求的语法,
如果控制力更强,您可以探索创建一个提供自定义 operator*()
和 operator->()
的实用程序 class 的可行性,这样您就可以 "mimic"智能指针(在没有 "smart reference" 的情况下)。我不确定这是否会提供您想要的语法。
您也可以探索 pimpl pattern/idiom (an opaque pointer),它没有回答问题,但提供了一种替代设计,可以更好地解决您遇到的问题。
我仍然不明白这样做的意义,但您可以使用 public 对私有静态成员的引用(顺便说一句,我不建议这样做):
struct A {
private:
struct B { int x, y; } static _b;
public:
// c++11 initialization, prior you need to initialize b in the
// constructor of A
B &b{_b};
};
A::B A::_b{0, 0};
然后:
int main() {
A a1, a2;
std::cout << a2.b.x << " ";
a1.b.x = 4;
std::cout << a2.b.x << std::endl;
}
输出:
0 4
正如@Niall 在评论中指出的那样,将引用作为属性将删除默认赋值运算符:
A a1, a2;
a2 = a1; // copy assignment is implicitly deleted
但是如果您需要它,您可以随时创建自己的,因为您不需要更新 b
:
struct A {
private:
struct B { int x, y; } static _b;
public:
B &b{_b};
A& operator= (A const&) {
// ok, no need to update this->b!
return *this;
}
};
A a1, a2;
a1 = a2; // ok
不过,我可以想到几个选项,就像所有单例一样,这些选项不是线程安全的:
- 您可以只使用
public
reference 来避免 accessors/mutators:
struct Settings {
private:
struct GeneralSettings {
int gi1, gi2;
} static _gs;
public:
int i1, i2;
GeneralSettings& gs;
Settings(int i1, int i2) : i1(i1), i2(i2), gs(_gs) {}
void do_something() const {
printf("%d %d %d %d\n", i1, i2, gs.gi1, gs.gi2);
}
};
- 你实际上可以 make it a full on singleton,尽管这需要一个访问器,而不是一个修改器,并且它会花费你
const
:
struct Settings {
struct GeneralSettings {
int gi1, gi2;
};
GeneralSettings& gs() {
static GeneralSettings gs;
return gs;
}
int i1, i2;
Settings(int i1, int i2) : i1(i1), i2(i2) {}
void do_something() {
printf("%d %d %d %d\n", i1, i2, gs().gi1, gs().gi2);
}
};