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调用。

常量的概念存在是有原因的。对我来说,它建立了一个非常重要的合同,在此基础上编写程序的进一步指令。但您可以通过以下几行操作:-

  • 使您的成员“可变”
  • 使“getter”恒定
  • 返回非常量引用
  • 这样,如果您需要在使用getter和非const用法(危险)的情况下维护const功能,就可以在LHS上使用const引用。但是现在程序员有责任维护类不变量

    正如前面在SO中所说的,丢弃最初定义的const对象的constness并使用它是U.B.所以我不会使用cast。同样,将一个非常量对象设置为常量,然后再次丢弃常量,看起来也不太好

    我在一些团队中看到的另一个编码准则是:-

    • 如果需要在类外修改成员变量,请始终 通过非常量成员函数返回指向它的指针
    • 任何成员函数都不能返回非常量引用。唯一常数 允许引用常量成员函数的形式

    这使得整个代码库具有一定的一致性,调用方可以清楚地看到哪些调用可以修改成员变量。

    对对象的
    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不仅仅是公开一个成员,它还做了重要的工作。然后将结果作为非常量公开是否是一个好主意