可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I would like to ask a question about methods' const-correctness. Let me illustrate the situation.
class MyClass
{
public:
...
void DiscussedMethod() { otherClass->NonConstMethod(); }
private:
OtherClass *otherClass;
};
I have a class MyClass
which keeps a pointer to OtherClass
. In DiscussedMethod
it calls OtherClass::NonConstMethod
which modifies some visible data.
I would like to know, whether it would be a good practice to make the DiscussedMethod
const
(since it doesn't modify any member data)? Would it be a bad practice? Or is both fine?
What if the OtherClass
kept a pointer to the MyClass
and in NonConstMethod
modified some of the MyClass
' data (meaning that the MyClass
member data would change during the DiscussedMethod
call). Would it be a bad practice to make the DiscussedMethod
const
then?
As far as I've been able to find out, the const
on a method is mostly a code documenting thing, so I would probably lean toward to not making the DiscussedMethod
const
, but I would like to hear your opinions.
EDIT: Some replies take the into account whether the object pointed to by otherClass
is owned by the MyClass
object. This is not the case in the scenario I'm working with. Lets say that both objects exist independently side by side (with the ability to modify each other). I think this analogy describes my situation quite well.
For example consider something like doubly-linked list, where each element is a class that keeps pointer to its neighbours and member variable color
. And it has method MakeNeighboursRed
which changes the color
of its neighbours but doesn't affect the calling object's state itself. Should I consider making this method const
?
And what if there was some possibility that MakeNeighboursRed
would call neighbour's MakeNeighboursRed
. So in the end the state of the object for which MakeNeighboursRed
has been called originally would change as well.
And I would like to thank you all for your opinions :-)
回答1:
If MyClass
owns the OtherClass
instance i wouldn't make DiscussedMethod
constant.
The same goes for classes, managing resources. I.e. the standard containers do not return non const references or pointers to the managed memory using const functions, although it would be "possible" (since the actual pointer holding the resource is not modified).
Consider
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;
}
The foo
could print two different values although an implementor of foo
would probably expect that two function calls on a const object will have the same behaviour.
For clarification:
The following is invalid according to the standard since the const version of operator[]
returns std::vector<T>::const_reference
which is a constant reference to the value type.
std::vector<int> const a = { /* ... */ };
a[0] = 23; // impossible, the content is part of the state of a
It would be possible if there was only one signature of this function, namely referece operator[] (size_t i) const;
, since the operation does not alter the internal pointers of the vector but the memory they point to.
But the memory, managed by the vector is considered to be part of the vectors state and thus modification is impossible through the const vector interface.
If the vector contains pointers, those pointer will still be unmodifiable through the public const vector interface, although the pointers stored in the vector may well be non const and it may well be possible to alter the memory they point to.
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 *
回答2:
In OOP object should be fully described by its state, available through its interface. Thus, const methods should not alter object's state, if these changes might be observed through the interface.
A good example is a mutable
mutex inside your class to guard some shared resources. It might be modified from const
method, since it does not introduce any changes observable via class interface.
回答3:
General rule of thumb is, that if you can make a member function const, you probably should. The reason for that is that it allows you to catch unintended behaviour and bug easier.
Another argument in favor would be that if you have this function as const you are allowed to call it on const object, so it isn't really a documentation thing.
回答4:
Overall it depends what the other class is. It's not black and white...
If otherClass
is a log object (for example) and you want to log the operation of the current object then it's perfectly fine calling it from a const function.
If the otherClass
is a container that for design (or implementation) purposes is implemented as a separate object than effectively a const function modifies the object making this a very bad idea.
I hope this helps.
回答5:
It's totaly incorrect to make DiscussedMethod
const
as it changes it's *this
state. The only loophole to this is making non-logically-part-of-object's-state member data mutable
so they can be changed in const
functions. This would be things like a member that hold a count for "number of times function x()
has been called". Any thing else is part of the object's state, and if a function changes it (at any level), that function isn't const
.
回答6:
I would like to know, whether it would be a good practice to make the DiscussedMethod const (since it doesn't modify any member data)?
otherClass
is member data, and it (or rather, the object it points to) gets modified.
Consider the semantics should the pointer to otherClass
be refactored to a fully-owned object... whether something is held as a pointer, reference, or object doesn't change the semantical ownership, IMO.