我似乎总是很难决定应该是static
和const
的类中的值是公共的还是私有的,并且使用静态公共方法进行访问。
class DeepThought
{
public:
static const int TheAnswer = 42;
};
与
class DeepThought
{
public:
static int GetTheAnswer() { return TheAnswer; }
private:
static const int TheAnswer = 42;
};
我希望以第一种方式做到这一点,但在我内心的某个地方感觉它破坏了封装,即使它是一个恒定值。第二种方式似乎并没有真正为表添加任何东西,但不必要地使代码混乱。
所以我问,这两种选择都存在根本错误吗?如果是,那又是什么?
答案 0 :(得分:5)
它们在语义上不相同。首选,因为它产生一个整数常量表达式,可用于数组边界,非类型模板参数,case表达式等。
int a[DeepThought::TheAnswer]; // ok
int b[DeepThought::GetTheAnswer()]; // broken
答案 1 :(得分:4)
纯粹从理论上讲,第二种选择是更正确的。在实际意义上,我同意你的看法 - 用getter函数包装常量值是没用的,无论如何都会被编译器删除。
根据我的经验,有时候更简单的方法会更好,即使它在某种程度上违反了OOP。
最后一点 - 我们过去常常使用枚举:
enum CONSTS
{
TheAnswer = 42,
};
答案 2 :(得分:4)
你应该考虑为什么 OOP“意识形态”说不暴露变量,只暴露出来。通常的论点是因为在未来的某个时刻,您可能需要访问该变量才能执行更复杂的操作。但是,开始时这种情况的可能性很小,当你谈论常量时,它变得更小。
我会继续将常量暴露为常数。但是,当没有当前需要getter时,我通常也会继续公开变量。 Python工作人员将此称为You Aren't Gonna Need It原则的应用程序。
答案 3 :(得分:2)
显而易见:
class DeepThought
{
public:
static int GetTheAnswer() { return 42; }
};
答案 4 :(得分:1)
你也可以使用第一个。考虑一下 - 你要将什么逻辑放入GetTheAnswer()
?你不能改变它的签名或它是静态的事实而不破坏它的界面考虑因素。这意味着除非你要开始制作非恒定的全局变量,这将是极其糟糕的,你在GetTheAnswer()
中没有任何东西可以放在TheAnswer
的constexpr中。分配给。
此外,使用GetTheAnswer()
可以做些什么是有限制的,例如,在第一个你可以使用常量的地址和GetTheAnswer()
,你不能,即使它是非常合理,你应该能够。
答案 5 :(得分:0)
class DeepThought {
public:
static const int i=10;
void f() { std::cout << i; }
};
然后你想要在运行时改变变量,它会变成这样:
class Singleton {
static Singleton &get() { static Singleton s; return s; }
int get_i() const { return i; }
};
class DeepThought {
public:
void f() { std::cout << Singleton::get().get_i(); }
};
然后在某些时候你会想要不止一个常数的实例,它会变成这样:
struct Data
{
int i;
};
class DeepThought {
public:
DeepThought(Data &d) : d(d) { }
void f() { std::cout << d.i; }
private:
Data &d;
};
int main() { Data d; DeepThought dt(d); dt.f(); }
在代码发展过程中,它会发生很大的变化,如果你有大量的代码,那么进行更改可能需要付出很大的努力。