制作一个修改类const之外的数据的方法是一个好习惯吗?

时间:2014-09-22 10:39:43

标签: c++ methods const

我想问一个关于方法的const-correctness的问题。让我来说明一下情况。

class MyClass
{
public:
    ...
    void DiscussedMethod() { otherClass->NonConstMethod(); }

private:
    OtherClass *otherClass;
};

我有一个班级MyClass,它会指向OtherClass。在DiscussedMethod中,它调用OtherClass::NonConstMethod来修改一些可见数据。

我想知道,制作DiscussedMethod const是否是一个好习惯(因为它不会修改任何成员数据)?这会是一种不好的做法吗?或者两者都很好?

如果OtherClass保留指向MyClass的指针并且NonConstMethod修改了某些MyClass'数据(意味着MyClass成员数据,该怎么办?会在DiscussedMethod来电期间发生变化。那么制作DiscussedMethod const会不会是一种不好的做法?

据我所知,方法上的const主要是代码记录的东西,所以我可能倾向于不做DiscussedMethod {{1} },但我想听听你的意见。

编辑:有些回复会考虑const指向的对象是否归otherClass对象所有。在我正在使用的场景中情况并非如此。让我们说两个对象并排存在(能够相互修改)。我认为这个类比很好地描述了我的情况。

例如,考虑像双向链表这样的东西,其中每个元素都是一个保持指向其邻居和成员变量MyClass的指针的类。它有方法color,它改变了邻居的MakeNeighboursRed但不影响调用对象的状态本身。我应该考虑制作这种方法color吗?

如果const可能会调用邻居的MakeNeighboursRed,那该怎么办?因此,最终调用MakeNeighboursRed的对象的状态也会发生变化。

我要感谢大家的意见: - )

6 个答案:

答案 0 :(得分:6)

如果MyClass拥有OtherClass个实例,我就不会使DiscussedMethod保持不变。

类,管理资源也是如此。即标准容器不会使用const函数返回非const引用或指向托管内存的指针,尽管它是“可能的”(因为保存资源的实际指针未被修改)。

考虑

class MyClass
{
public:
    bool a() const { return otherClass->SomeMethod(); }
    void b() const { otherClass->NonConstMethod(); }
private:
    OtherClass *otherClass;
};

void foo (MyClass const &x)
{
    cout << boolalpha << x.a() << endl;
    x.b(); // possible if b is a const function
    cout << boolalpha << x.a() << endl;
}

虽然foo的实现者可能期望const对象上的两个函数调用具有相同的行为,但foo可以打印两个不同的值。

澄清:

根据标准,以下内容无效,因为operator[]的const版本返回std::vector<T>::const_reference,这是对值类型的常量引用。

std::vector<int> const a = { /* ... */ };
a[0] = 23; // impossible, the content is part of the state of a

如果只有一个这个函数的签名,即referece operator[] (size_t i) const;,就有可能,因为操作不会改变向量的内部指针,而是改变它们指向的内存。

但是由向量管理的内存被认为是向量状态的一部分,因此通过const向量接口无法进行修改。

如果向量包含指针,那么这些指针仍然可以通过公共const向量接口进行修改,尽管存储在向量中的指针很可能是非常量的,并且很可能改变它们指向的内存。

std::vector<int*> const b = { /* ... */ };
int x(2);
b[0] = &x; // impossible, b is const
*b[0] = x; // possible since value_type is int* not int const *

答案 1 :(得分:4)

在OOP对象中,应该通过其接口提供的状态来完整描述。因此,如果可以通过接口观察到这些变化,则const方法不应该改变对象的状态。

一个很好的例子是类中的mutable互斥锁来保护一些共享资源。它可能会从const方法修改,因为它不会通过类接口引入任何可观察到的更改。

答案 2 :(得分:3)

一般的经验法则是,如果你可以使一个成员函数const,你可能应该。这样做的原因是它可以让你更容易地捕捉到意想不到的行为和错误。

另一个有利的论点是,如果你将这个函数作为const,你可以在const对象上调用它,所以它实际上不是文档。

答案 3 :(得分:2)

总的来说,这取决于其他课程。它不是黑白的......

如果otherClass是一个日志对象(例如),并且您想记录当前对象的操作,那么从const函数调用它就完全没问题。

如果otherClass是一个容器,设计(或实现)目的是作为一个单独的对象实现而不是有效的const函数修改对象使这个想法非常糟糕。< / p>

我希望这会有所帮助。

答案 4 :(得分:1)

使DiscussedMethod const更改为*this状态完全不正确。唯一的漏洞是使非逻辑 - 对象的状态成员数据mutable,以便可以在const函数中进行更改。这就像是一个成员,其中包含“已调用函数x()的次数”。其他任何东西都是对象的状态的一部分,如果一个函数改变了它(在任何级别),那么该函数不是const

答案 5 :(得分:1)

  

我想知道,制作DiscussedMethod const是否是一个好习惯(因为它不会修改任何成员数据)?

otherClass 成员数据,它(或更确切地说,它指向的对象)会被修改。

考虑到指向otherClass的指针应该重构为完全拥有的对象的语义......是否某些东西被保存为指针,引用或对象不会改变语义所有权,IMO。