优雅的解决scheme,复制,const和非const,getters?
你有没有讨厌它
class Foobar { public: Something& getSomething(int index) { // big, non-trivial chunk of code... return something; } const Something& getSomething(int index) const { // big, non-trivial chunk of code... return something; } }
我们不能用另一个实现这个方法,因为你不能从const
版本中调用非const
的版本(编译器错误)。 需要const
非const
。
有没有一个真正优雅的解决scheme,如果没有,最接近的是什么?
我从有效的C ++书籍中回想起,实现它的方法是通过从其他函数中抛出const来实现非const版本。
这不是特别漂亮,但它是安全的。 因为调用它的成员函数是非const的,所以对象本身是非const的,并且允许抛出const。
class Foo { public: const int& get() const { //non-trivial work return foo; } int& get() { return const_cast<int&>(static_cast<const Foo*>(this)->get()); } };
怎么样:
template<typename IN, typename OUT> OUT BigChunk(IN self, int index) { // big, non-trivial chunk of code... return something; } struct FooBar { Something &getSomething(int index) { return BigChunk<FooBar*, Something&>(this,index); } const Something &getSomething(int index) const { return BigChunk<const FooBar*, const Something&>(this,index); } };
显然你仍然有目标代码重复,但没有源代码重复。 与const_cast方法不同的是,编译器将检查两个版本的方法的const正确性。
您可能需要将BigChunk的两个有趣实例声明为该类的朋友。 这是朋友的一个很好的使用方式,因为朋友的function隐藏在朋友的旁边,所以不存在无约束的耦合(哦!)的风险。 但我现在不会尝试这样做的语法。 随意添加。
BigChunk有可能需要尊重自我,在这种情况下,上述定义的顺序不会奏效,并且需要一些前向声明来整理。
另外,为了避免在头文件中findBigChunk,并决定实例化并调用它,即使它在道德上是私有的,也可以将整个文件移动到FooBar的cpp文件中。 在匿名的命名空间。 与内部联系。 还有一个标语“小心豹子”。
尝试通过重构代码来消除getter。 如果只有很less的其他东西需要东西,请使用朋友函数或类。
一般来说,Getters和Setter打破封装,因为数据暴露在世界上。 使用朋友只将数据公开给选定的几个,所以给出更好的封装。
当然,这并不总是可能的,所以你可能会被吸收者困住。 至less,大部分或所有的“不重要的代码块”应该在一个或多个私有函数中,由两个getter调用。
我会将const强制转换为非const(第二选项)。
为什么不把普通的代码放到一个单独的私有函数中,然后让另外两个调用呢?
对对象的const
引用是有意义的(你对这个对象的只读访问进行限制),但是如果你需要允许一个非const
引用,那么你也可以让这个成员变成公共的。
我相信这是一个拉斯科特·迈耶斯(Efficient C ++)。
“const”的概念是有原因的。 对我来说,它build立了一个非常重要的合同,根据哪一个程序的进一步的指示写。 但是你可以在下面几行做一些事情:
- 让你的成员“可变”
- 使'getters'const
- 返回非const引用
有了这个,你可以在LHS上使用const引用,如果你需要在使用getter的时候保持const函数,而非const使用(危险的)。 但现在程序员有责任维护类不变式。
正如前面所述,抛弃原来定义的const对象的常量,并使用它是一个UB所以我不会使用强制转换。 另外做一个非const对象const,然后再抛出const不会看起来太好。
另外一些编码指导方针是我在某些团队使用的:
- 如果一个成员variables需要在类之外修改,总是通过一个非const成员函数返回一个指向它的指针。
- 没有成员函数可以返回非const引用。 const成员函数只允许const引用。
这样可以在整个代码库中保持一定的一致性,调用者可以清楚地看到哪些调用可以修改成员variables。
我敢build议使用预处理器:
#define ConstFunc(type_and_name, params, body) \ const type_and_name params const body \ type_and_name params body class Something { }; class Foobar { private: Something something; public: #define getSomethingParams \ ( \ int index \ ) #define getSomethingBody \ { \ return something; \ } ConstFunc(Something & getSomething, getSomethingParams, getSomethingBody) };