const成员函数返回对象的constness

时间:2009-05-22 19:04:29

标签: c++

关于const成员函数的返回值是否应该是const,有什么好的经验法则?这是我倾向于做的事情,但我很挣扎 模棱两可的场景。

class foo
{
    public:
        // if the returned object is conceptually
        // (and therefore usually literally but not even necessarily) 
        // owned by *this*,
        // then a const ptr should be returned
        const ownedByFoo *getOwnedByFoo() const { return m_ownedByFoo; }
        ownedByFoo *getOwnedByFoo() { return m_ownedByFoo; }

        // what's a poor boy to do here?
        // veryRelatedToFoo might be a conceptual contemporary or parent
        // of Foo. Note naming the function "find..." instead of "get.."
        // since *get* implies the object holds it as a data member but
        // that may not even be the case here. There could be a
        // standalone container that associates foo and veryRelatedToFoo.
        // Should constness be symmetrical here?
        const veryRelatedToFoo *findVeryRelatedToFoo() const;
        veryRelatedToFoo *findVeryRelatedToFoo();

        // If the returned object is only (conceptually)
        // peripherally related to *this*, 
        // the returned object probably shoudn't be const, even if
        // foo happens to have one of these as a direct data member,
        // since we don't want to give away the implementation details of
        // Foo and it may hold peripherallyRelatedToFoo simply for performance
        // reasons, etc.
        peripherallyRelatedToFoo *findPeripherallyRelatedToFoo() const

    ...
};

另外一个注意事项是,一旦你有不对称的常数,你就可以 请求const对象A返回对象B,然后让对象B返回对象A,并且 那么你已经设法绕过了对象A的预期常量。

5 个答案:

答案 0 :(得分:1)

任何常量都比你能用多种语言找到的更多!

一旦你理解(如你所知)“物理常数”和“逻辑常数”之间的区别,那么“含糊不清”的情景仍然只是:受到辩论。例如,考虑mutable关键字存在的事实。

我认为你有正确的总体思路:除此之外,它都是有争议的和主观的,并根据特定的问题和约束等而变化。

我倾向于“没有规则的例外”,所以我避免从const方法返回指向非const的指针;但是我想我可以想象一些我可能会受到诱惑的场景......尽管我可能更倾向于决定让这个方法成为非常量。

答案 1 :(得分:1)

(我忽略了你直接返回对象状态这一事实,这通常是一个坏主意,因为它破坏了封装 - 我将其视为“示例代码”)

两者之间没有关系。 const成员函数是不修改基础对象的成员 - “在执行时”。没有承诺或要求返回值为const。一旦方法返回,const - ness合约就“结束”。我认为你感到困惑,因为你试图将返回值与产生它的方法联系起来。

返回值是const还是const取决于返回值的性质以及要归因于该方法的语义。

在您的特定第一种情况下,这两种方法应该返回相同的const - ness。 const重载可能不是你想要使用的。如果你想要这两种变体,我可能会明确地说明这一点:

const ownedByFoo *getOwnedByFoo() const { return m_ownedByFoo; }
ownedByFoo *getOwnedByFooForEdit() { return m_ownedByFoo; }

这样就没有歧义,也没有神秘的两者搭讪。请注意,我创建了第二个非const,因为我们可能不希望客户端代码修改const对象上的m_ownedByFoo。这是从方法的语义(“返回内部状态”)中产生的要求,而不是方法的const - ness和返回值的const之间的联系。如果返回的值不是对象状态的一部分,我可能会做其他事情。

答案 2 :(得分:0)

不要从const方法返回非const指针或对成员数据的引用。

答案 3 :(得分:0)

如果返回的引用是const,则使函数const,如果不是,则不要。您应该尽量避免返回对成员数据的非const引用,因为这会破坏封装,除非该类主要是某种容器类。

答案 4 :(得分:0)

如果返回非const引用/指针将允许调用者使该类应该维护的不变量无效,则不返回该非const引用/指针。 (它应该是常量。)