复制,常量和非常量,吸气剂的优雅解决方案? [重复]

问题描述 投票:107回答:8

你有没有恨它

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版本。

有没有一个真正优雅的解决方案,如果没有,最接近一个?

c++ const
8个回答
99
投票

我从其中一本Effective C ++书籍中回忆一下,这样做的方法是通过从另一个函数中抛弃const来实现非const版本。

它不是特别漂亮,但它是安全的。由于调用它的成员函数是非const的,因此对象本身是非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());
    }
};

27
投票

怎么样:

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的两个有趣实例声明为类的朋友。这是一个很好用的朋友,因为朋友的功能隐藏在靠近朋友的地方,所以不存在无约束耦合的风险(哦!)。但我现在不会尝试这样做的语法。随意添加。

有可能BigChunk需要尊重自己,在这种情况下,上面的定义顺序不会很好地工作,并且需要一些前向声明来解决它。

此外,为了避免在标题中找到BigChunk并决定实例化并调用它,即使它在道德上是私有的,你可以将整个批次移动到FooBar的cpp文件中。在匿名命名空间中。内部联系。还有一个标语“小心豹子”。


7
投票

我会将const转换为非const(第二个选项)。


5
投票

为什么不将公共代码拉出到一个单独的私有函数中,然后让另外两个调用它?


4
投票

尝试通过重构代码来消除getter。如果只有极少数其他东西需要Something,请使用友元函数或类。

通常,Getters和Setter打破封装,因为数据暴露给世界。使用friend只会将数据公开给少数几个,因此可以提供更好的封装。

当然,这并不总是可能的,所以你可能会被吸气剂困住。至少,大多数或所有“非平凡的代码块”应该在一个或多个私有函数中,由两个getter调用。


3
投票

const对该对象的引用是有意义的(您对该对象的只读访问权限有限制),但如果您需要允许非const引用,您也可以将该成员公开。

我相信这是一个la Scott Meyers(高效C ++)。


2
投票

'const'的概念是有原因的。对我来说,它建立了一个非常重要的合同,在此基础上编写了程序的进一步指令。但你可以做以下几点: -

  1. 让你的成员'变成'
  2. 制作'getters'const
  3. 返回非const引用

有了这个,如果你需要在使用getter和非const使用(危险)的地方维护const功能,可以在LHS上使用const引用。但是程序员现在有责任维护类不变量。

正如之前在SO中所说的那样,抛弃原始定义的const对象的常量并使用它是U.B.所以我不会使用演员阵容。同时使非const对象const然后再次抛弃constness看起来不太好。

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

  • 如果需要在类外部修改成员变量,则始终通过非const成员函数返回指向它的指针。
  • 没有成员函数可以返回非const引用。 const构件函数只允许const引用。

这允许整个代码库中的一些一致性,并且调用者可以清楚地看到哪些调用可以修改成员变量。


-2
投票

我敢建议使用预处理器:

#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)
};
© www.soinside.com 2019 - 2024. All rights reserved.