在C ++中,是一个const方法返回一个指向非const对象的指针被认为是不好的做法吗?

时间:2010-09-11 04:21:22

标签: c++

在C ++中,是一个const方法返回一个指向非const对象的指针被认为是不好的做法吗?例如。考虑以下方法:

// Makes perfect sense
bool isActive() const { return m_isActive; }

// Makes perfect sense, both consts ensure nothing is modified
const SomeObject* someObject() const { return m_someObject; }

// Makes perfect sense, no const because SomeObject is mutable,
// thus MyClass is indirectly mutable
SomeObject* someObject() { return m_someObject; }

// Makes no sense, if you're just returning a pointer to a const object,
// then the method should clearly be const since nothing can be modified
const SomeObject* someObject() { return m_someObject; }

最后一个组合让我感到困惑:以下是不好的做法?

SomeObject* someObject() const { return m_someObject; }

因为方法返回的类不是const,而是方法,所以它有点无意义,因为你可以修改SomeObject,因此间接修改你的类......所以形式被认为是不良做法例如你应该只使用以下其中一种来代替它吗?

const SomeObject* someObject() const { return m_someObject; }
SomeObject* someObject() { return m_someObject; }

现实世界的情况:我正在写一部有Game课程的智能手机游戏。 Game类包含几个返回指向实用程序类的指针的方法,如InputManagerAudioManager等。

class Game
{
public:
    InputManager* inputManager() const { return m_inputManager; }
    ...

private:
    InputManager* m_inputManager;
    ...
}

使inputManager() const成为一个任何意义,因为它返回的对象不是吗? (并且不应该,因为InputManager需要变更其状态才能更新,等等。)

或者我应该删除方法的const修饰符以更准确地反映方法的行为?这样,如果我有一个const Game,即使inputManager()Game,我也无法调用Game然后混淆const的输入管理器

5 个答案:

答案 0 :(得分:3)

这取决于非const指针是指向const对象内的某个东西,还是它是新分配的内存是否可变。

考虑返回字符串副本的内容;即使原始字符串是const,返回的副本也可以是非常量的。副本的所有权从方法传递到调用代码;确保副本被适当地破坏现在是调用代码的问题(很可能是一个非常小的问题)。

但是,从const对象内部返回一个非const指针是一个非常糟糕的主意。

答案 1 :(得分:2)

这完全可以接受。 const方法意味着您不会修改您正在调用其方法的对象 - 它没有说明任何其他对象。当然,这个对象可能是“这个”的一部分,或者它可能是“这个” - 但这超出了这一点。

“const”通常更像是一个承诺而不是任何东西,但基本思想是相同的 - 一个const方法说“this”是const,而且就是所有。

答案 2 :(得分:0)

在我看来,返回一个成员指针是一个坏主意,无论const是否。

当一个对象返回其私有成员的句柄时,其他人可以通过此句柄更改私有成员。对象的状态可能不一致并导致很多麻烦。即使有一个const,调用者仍然可以使用const cast来绕过这个检查。因此,返回对象的任何私有成员的句柄并不是一个好主意。

答案 3 :(得分:0)

我不认为const在这里很重要。

通常会将句柄(指针,引用)返回到属性:

  • 它将用户绑定到特定的实现,使其无法更改
  • 它使得不可能强制执行不变量(非常量版本),你现在可能没有这样的,但你现在从未有过将来会发生的事情

如果您开始直接访问属性,则它们与public一样好。

示例:

class Foo
{
public:
  std::vector<Bar> const& bars() const; // Ooops, impossible to move to a `deque`
                                        // or to enable polymorphic behavior
private:
  std::vector<Bar> mBars;
};

你最好按值返回,这样一来,如果你改变你的内部,你总是可以提供一个新的方法,并在旧的方法中进行一些转换,不要破坏你的界面(标记它已弃用,全部)。

请记住:人们因暴露他们的私人而被送进监狱!

答案 4 :(得分:0)

在您的情况下,GameInputManager对象似乎是单身人士。如果是这种情况,您只需要确保只存在一个Game实例(只包含一个InputManager),并跳过const装饰器。如上所述,在这种情况下,我会返回对包含对象的引用,没有指针。