我有一个C++功能的想法,我想知道是否可以创建.
假设我希望'MyClass'中的私有变量只能由两个函数访问,即公共getter和setter.也就是说,如果MyClass的另一个公共或私有函数试图获取或更改我的超私有变量的值,我将得到编译错误.但是,getter和setter表现正常.
有任何想法吗?
编辑1:用例是让getter/setter执行错误检查或其他形式的逻辑.我甚至不希望类本身直接触及变量.
编辑2:这样的话:
template <class T>
class State{
private:
T state;
public:
State()
{
state = 0;
}
T getState()
{
return state;
}
void setState(T state)
{
this->state = state;
}
};
Run Code Online (Sandbox Code Playgroud)
然后任何类都可以继承它并仅通过getter/setter访问'state'.当然,如果没有根据你想要的逻辑修改getter和setter,这个类就没用了.
pmr*_*pmr 30
您可以将变量包装在一个类中,并将其设置为私有和一个const T&getter.比你声明包含类的get和set成员函数作为该包装器的朋友.现在,您将包装类保留为原始类中的成员.这应该达到你想要的,尽管它看起来很难维护而且不是很有用.
所以这里有一些虚拟实现,展示了它是如何工作的(注意整个new VeryPrivateWrapper业务只是一个古怪的方式来声明,unique_ptr更有帮助):
class VeryPrivateWrapper;
class Original {
VeryPrivateWrapper* m_wrapper;
public:
Original();
// imagine that I remembered the rule of three here
void set(int);
void other();
};
// make this a template for more fun
class VeryPrivateWrapper {
int m;
public:
const int& get() const { return m; }
// !!!
// the important bit
// !!!
friend void Original::set(int);
};
Original::Original() : m_wrapper(new VeryPrivateWrapper) {}
void Original::set(int i) {
m_wrapper->m = i;
}
void Original::other() {
// this borks as we would like
// m_wrapper->m = 23;
}
int main()
{
Original o;
o.set(3);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
mar*_*h44 10
我相信这就是你要求的.这是可取的吗?有些人会认为这是令人厌恶的.
如果您决定使用它,您可能希望从宏中提取公共Get和Set并手动编写.
#define SUPER_PRIVATE(c,t,m) \
template <typename C, typename T> \
class SuperPrivate##m { \
friend T& C::Get##m(); \
friend void C::Set##m(const T&); \
T value; \
}; \
public: \
t& Get##m() { return m.value; } \
void Set##m(const t& value) { m.value = value; } \
private: \
SuperPrivate##m<c,t> m;
class SomeClass
{
public:
SomeClass()
{
SetX(42);
SetY(58);
}
int DosomethingWithX() { return GetX() * 2; }
// int DosomethingWithX2() { return X.value * 2; } // error
// int DosomethingWithX3() { return X; } // error
SUPER_PRIVATE(SomeClass, int, X);
SUPER_PRIVATE(SomeClass, int, Y);
};
int main()
{
SomeClass someObject;
int x1 = someObject.GetX();
int y1 = someObject.GetY();
someObject.SetY(89);
int y2 = someObject.GetY();
int x2 = someObject.DosomethingWithX();
}
Run Code Online (Sandbox Code Playgroud)
我会给变量添加一个非常丑陋的名称,并为getter/setter添加一个很好的名称:
class Foo
{
private:
int _hey_do_not_use_me_im_super_private_whatever;
public:
int get_whatever() const
{
//extra logic
return _hey_do_not_use_me_im_super_private_whatever;
}
void set_whatever(int we)
{
//extra logic
_hey_do_not_use_me_im_super_private_whatever = we;
}
};
Run Code Online (Sandbox Code Playgroud)
评论表明超级私人意味着什么将是继承您的代码的人最欢迎的.