C++ 复制、常量和非常量、getter的优雅解决方案?
你不讨厌你有C++ 复制、常量和非常量、getter的优雅解决方案?,c++,constants,C++,Constants,你不讨厌你有 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 cod
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
版本需要一个cast
是否有真正优雅的解决方案,如果没有,最接近的解决方案是什么?我会将常量转换为非常量(第二个选项)。尝试通过重构代码来消除getter。如果只有极少数其他东西需要,请使用友元函数或类 通常,getter和setter会破坏封装,因为数据是公开的。使用friend只将数据公开给少数人,因此提供了更好的封装
当然,这并不总是可能的,所以您可能会被getter卡住。至少,“非平凡代码块”的大部分或全部应该在一个或多个私有函数中,由两个getter调用。常量的概念存在是有原因的。对我来说,它建立了一个非常重要的合同,在此基础上编写程序的进一步指令。但您可以通过以下几行操作:-
- 如果需要在类外修改成员变量,请始终 通过非常量成员函数返回指向它的指针李>
- 任何成员函数都不能返回非常量引用。唯一常数 允许引用常量成员函数的形式
这使得整个代码库具有一定的一致性,调用方可以清楚地看到哪些调用可以修改成员变量。对对象的
const
引用是有意义的(您对该对象的只读访问设置了限制),但如果需要允许非const
引用,你也可以公开这个成员
<> P>我相信这是一个La Scott Meyers(高效C++)。 < P>我从一本有效的C++书籍中回忆到,这样做的方法是通过从其他函数中去掉const来实现非const版本。 它不是特别漂亮,但很安全。因为调用它的成员函数是非常量的,所以对象本身是非常量的,并且允许丢弃常量
class Foo
{
public:
const int& get() const
{
//non-trivial work
return foo;
}
int& get()
{
return const_cast<int&>(const_cast<const Foo*>(this)->get());
}
};
class-Foo
{
公众:
常量int&get()常量
{
//琐事
返回foo;
}
int&get()
{
返回const_cast(const_cast(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);
}
};
模板
OUT BigChunk(在self中,int索引){
//大而不平凡的代码块。。。
归还某物;
}
结构FooBar{
Something&getSomething(int索引){
返回BigChunk(这个,索引);
}
constsomething&getSomething(int-index)const{
返回BigChunk(这个,索引);
}
};
显然,您仍然会有目标代码复制,但没有源代码复制。与const_cast方法不同,编译器将检查方法的两个版本的const正确性
您可能需要将BigChunk的两个有趣的实例化声明为类的朋友。这是friend的一个很好的用途,因为friend函数隐藏在离friend对象很近的地方,所以不存在无约束耦合的风险(ooh-er!)。但我现在不会尝试这样做的语法。请随意添加
BigChunk可能需要遵从self,在这种情况下,上述定义顺序将无法很好地工作,需要一些向前声明来解决这个问题
此外,为了避免在头文件中找到BigChunk,并决定实例化和调用它,即使它在道德上是私有的,您可以将全部内容移动到FooBar的cpp文件中。在匿名命名空间中。具有内部连接。还有一个牌子上写着“小心豹子”。为什么不把普通代码拉到一个单独的私有函数中,然后让另外两个调用它呢?我敢建议使用预处理器:
#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)
};
它可以工作,但我不认为这很优雅……贝诺:不,不雅致,但实用。+ 1:我认为这是一个为数不多的有效使用const铸造-它绝对击败代码复制和/或跳过各种箍。我不反对:)如果<代码>某物< /代码>曾经得到声明const,那么您将遇到一个您不会注意到的问题,因为您的程序仍在编译。公共成员?不是很糟糕…我可能会收回这一点,因为我没有读过关于“非平凡代码”的部分,使那些函数不能直接获取。实际上,当你想到它的时候。如果不被滥用,公众成员是这个问题最简单、最直接的答案。如果任何人都可以通过使用适当的getter/setter来操纵它们,那么实际上它是一个公共成员。也许将其公开是更好的代码,因为它告诉客户,“我是一个公开的成员,你想对我做什么就做什么”。这比实现两种类型的getter要简单得多,“您还可以公开成员”。不,因为getter中有一个“大的、不平凡的代码块”。这个getter不仅仅是公开一个成员,它还做了重要的工作。然后将结果作为非常量公开是否是一个好主意