a const member function, returning a pointer to a non const member variable, why would it be good?
I work in a large collaboration (of mostly non-professional programmers, I being one of them). I regularly see examples of the following
void 开发者_C百科T::DoChanges(I i); // will make changes to internal structure of T (non-const)
V T::GetValue();
class A
{
private:
T* fMember;
public:
A();
T* GetMember() const {return fMember;}
}
, Where a use-case would be
A a;
I i;
a->GetMember()->DoChanges(i);
V v = a->GetMember()->GetValue();
This practice violates a tenant drilled into me when i took programming courses, i.e. that const refers not only to the bitwise structure of the class instance, but the internal logical structure. Under this philosophy, the member function should take the following forms:
T* GetMember() {return fMember;}
const T* GetMember() const {return fMember;}
I have heard that some people think that const should only refer to members, speaking strictly using the c++ terminology. How/why would someone argue for this type of practice?
Making the member function gives the indication to the users of this function that it will not modify any class members.
The returned member may or maynot be const
but making the member function const gives the users of the class a clear indication of the behavior of function.
It's largely dependent on the design, but for your case, I don't see why you need two prototypes.
The question you need to ask yourself is whether you want people altering your T
member via the get
.
If you do, your prototype should look like:
T* GetMember() const {return fMember;}
If you don't, make the return const:
const T* GetMember() const {return fMember;}
The function doesn't have to be const
, but consider it can be without a problem. That being said, would you call the function inside a different non-const member function? Because if you plan on doing so, it won't work since it's not const
.
Since you only return a pointer to a member and not actually change anything, I would go with making the function const
. This also acts as a directive to others working on the project that the function doesn't modify anything internally.
The choice on whether the return should be const
or not is entirely design-dependent.
I was going to reply that this is a question of design, and it's your choice whether you are happy with mutable accessor (in which case you go for the first, const
version), or if you want to forbid constant references to modify the pointee (in which case you go for the second, two-overloads version).
But coming to think of it, I think your question demonstrates that getters and setters are a bad idea in general. You shouldn't just blindly forward class members (in which case you might as well just make them public members). Rather, your class should offer a meaningful interface that abstracts away the implementation. So ideally the fact that there's a raw pointer in your class should never be of concern to the user, and your interface functions take care of making the relevant logical constness guarantees.
If you choose to forgo these OO design principles, then I suppose you're on your own, and you should do whatever suits your overall design best.
Arguably, the logical structure of the class is irrelevant of what changes you make to what's pointed to. For example, consider a linked list node. The node is constant as long as the next (and possibly previous) pointers are the same- but the node doesn't care if you change the next node. In addition, T itself might just be an immutable object in design anyway and therefore const T
is a meaningless distinction.
It's perfectly fine, and useful in the same cases that a T* const
is.
Consider a hash-table being accessed from multiple threads. The internal structure needs to not change while another thread is accessing the object, but that doesn't mean the hash-table needs to contain only const pointers. (Locking the individual objects is much more scalable than locking the whole data structure.)
精彩评论