我在MacOS Sierra
上使用带有clang的C ++ 14。我想按设计强制执行规则。以下是规则。
我班上有一个成员变量说:
unsigned int m_important_num;
我班上有4种方法。
fun1();
fun2();
fun3();
fun4();
目的:
我只希望fun2()
能够更改m_important_num
的值。
问题:
如果除fun2()
以外的任何方法更改变量,是否可能使编译器出错?
一种可能的方法是声明const以某种方式授权fun2()
来改变const变量?这是一个好的解决方案吗?或者他们是更好的解决方案?
次要问题:
尝试做这样的事情是错误的设计吗?
答案 0 :(得分:10)
封装它。将m_important_num
放在自己的类中。在现有类中聚合它。有一个吸气剂。然后将fun2()
作为内部类的成员函数。
答案 1 :(得分:10)
排序,附加图层:
class S1 {
public:
void fun2() { /*Modify m_important_num */ }
unsigned int getImportantNum() const { return m_important_num;}
private:
unsigned int m_important_num;
};
class S2 : private S1
{
public:
void fun1();
using S1::fun2; // or void fun2() {S1::fun2();}
void fun3();
void fun4();
};
正如Yakk评论的那样,如果func2
需要访问S2
成员,CRTP可以解决这个问题:
template <typename Derived>
class S1 {
public:
void fun2() { asDerived().foo3(); /*Modify m_important_num */ }
unsigned int getImportantNum() const { return m_important_num;}
private:
Derived& asDerived() { return stataic_cast<Derived&>(*this); }
private:
unsigned int m_important_num;
};
class S2 : private S1<S2>
{
// friend class S1<S2>; // If required.
public:
void fun1();
using S1::fun2; // or void fun2() {S1::fun2();}
void fun3();
void fun4();
};
答案 2 :(得分:1)
如果您想阻止某个方法修改该类中的任何成员,您可以使用尾随的const
标识符:
class something{
private:
unsigned int var;
public:
void fun1() const;
void fun2();
void fun3() const;
void fun4() const;
}
此处,只有fun2()
才能修改变量。
答案 3 :(得分:1)
我对Jeffrey解决方案的一点变体(如果我理解正确的话):将变量放在内部类中并使其成为private
;创建一个public
getter并将func2()
friend
设置为内部类。
我的意思是
struct foo
{
int f1 () { return b0.getVal(); }; // you can read `val` everywhere
void f2 () { b0.val = 42; }; // you can write `val` in f2()
void f3 () { /* b0.val = 42; ERROR ! */ }; // but only in f2()
class bar
{
private:
int val = 24;
public:
int getVal () { return val; }
friend void foo::f2 ();
};
bar b0;
};
换句话说:friend
是你的朋友。
答案 4 :(得分:1)
我知道有很多好的答案,但在你的问题中还有一个你可以提到的选项:
一种可能的方法是声明const以某种方式授权fun2()来改变const变量?
#include <iostream>
using uint = unsigned int;
class Test
{
const uint num;
public:
Test(uint _num)
:
num(_num)
{}
uint get_num() const
{
return num;
}
void can_change_num(uint _new_num)
{
uint& n(const_cast<uint&>(num));
n = _new_num;
}
void cant_change_num(uint _new_num)
{
// num = _new_num; // Doesn't compile
}
};
int main()
{
Test t(1);
std::cout << "Num is " << t.get_num() << "\n";
t.can_change_num(10);
std::cout << "Num is " << t.get_num() << "\n";
return 0;
}
可生产
Num is 1
Num is 10
答案 5 :(得分:1)
您已经对主要问题得到了很多好的答案。我会尝试解决第二个问题。
尝试做这样的事情是错误的设计吗?
很难说你不了解你的设计。一般来说,在代码审查期间检测到的任何类似内容都会引发一个大红旗。在具有复杂逻辑/实现的大类的情况下,这种保护是有意义的。否则你为什么要加倍努力让你的代码变得更复杂?你寻求的事实可能表明你的课程变得无法管理。
我建议考虑将它拆分为具有更好定义逻辑的较小部分,您不必担心这些错误很容易发生。