I'm sort of duplicating this post because it requested that I start a new thread because I was replying to an old one, but here is a statement that prompted my questions: "Accessors should be const methods at the very least, because the object state isn't changed in the body." I came across this because of cv-qualifiers errors that I had because of a const that was introduced through netbeans automatically generating getter functions for me. When I removed all the const 's from my code, I was fine again. However, Radical Edward seems to be an expert and suggests the statement above, as was automatically done for me, that const is something that should be used. Does anyone have a reason for using a const? Does anyone have an explanation for what a const is? All I've ever seen about const is that they get in the way of compilations, adding headaches of const_cast 'ing and stuff. Is there a benefit to const 's? And what is this _state thing?
Well you are stepping into the realm of const-correctness which is this idea that if you want to be rigorous, you should put const everywhere where a variable is constant or required to be constant. You are right that a lot of people (especially beginners) are frustrated at the const qualifier because it causes annoying errors when part of the code is const-correct and part of it is not. The basic problem is that const-correctness has a spreading effect (which is very desirable). If you make your library completely and rigorously const-correct, it sort of forces people that use your library to be const-correct, at least to a certain level.
But why?
Well experienced programmers like to know what a function does without having to look at the code in it (only at the interface or function prototypes). const qualifiers are a way to announce to outside programmers not to worry that a particular object or function-parameter may change, especially when it is not obvious. The C++ language is strongly typed and thus spreads this qualifier around to sort of enforce the law. This means:
class Time {
private:
int hour;
int minute;
public:
int getHour() const; //const means that reading the value of hour does not change any data in the Time object.
int getMinute() const; //same here, the caller is aware that this function does not modify the Time object.
int getNonConstHour(); //say you omit const.
};
ostream& operator <<(ostream& out, const Time& value) { //here the caller knows that the parameter value will not be altered.
//here, you can call the const methods because they also guarantee no modification of "value".
out << value.getHour() << ":" << value.getTime();
//however, calling the non-const method will not be allowed:
out << value.getNonConstHour(); //ERROR!
return out;
};
By spreading this law, it makes everything a bit safer, although there are workarounds for special situations. However, many beginners mistakenly think that const-correctness is restrictive and annoying, but that is because beginners make beginner's mistakes in the design of their software and then the const-correctness does what it is supposed to do which is filtering out poorly designed code, and that gets in the way of those dirty hacks that beginners do to rescue a poorly designed software architecture (I know, I have done my share of those in the past). That is the main purpose of const-correctness: you apply it everywhere you can, and whenever you try to do something that reflects poor software design, there is a better chance the compiler catches it and that helps you better design the software. If you run into const-relate compiler errors, first make sure use of const qualifiers are actually correct, then modify your method such that you don't violate the const requirements (at very last resort: mutables or const_casts).
So, no, it is not a complication or a restriction, it is a powerful tool that enables better software design methodology.
Ok, this is very useful because it is helping me see what const means. I'm not seeing any more computational power coming out of it--is that correct? If I get it right, I'm not actually going to speed up my code or anything by using const--it just make the code more readable or bug proof, right?
I'm a little confused as to why one would want to have a limitation on whether they could change a value. I thought C++ was trying to get away from that type of thing by allowing &'s in the arguments so it would be easier to make any variable changeable. I can see how it would make me more comfortable to use a function that I didn't understand or have time to investigate. However, I can't imagine a reason I would want to write something for someone to use if they didn't understand it or that would worry about a programmer comfort level. For clarification's sake, how is "poorly designed software architecture" defined in this case?, and how would a "well designed software architecture" be defined? Is that more of a perspective of well designed for practical teams of programmers themselves to benefit, or is there actually some more efficient use of the computer itself somehow through a differently designed software architecture? I can definitely see the benefit of readability and/or safety from an efficiency of the programmer perspective. However, I can't think of any reason I would want to limit the ability to change a variable from the perspective of improving software performance--but then again, maybe there is a way to use data of this type more efficiently in the machine somehow, or something? I suppose it does make a lot of sense in a way if you are doing it for the sake of proof of debugging that aspect of it. I often feel that there is no way to completely be sure that a program has no bugs anywhere at all. I could probably benefit from this in that regard as a specific feature which I could be completely confident in.
Here's a specific example of why I'm still a bit hesitant. Suppose I write a class that has a const variable parameter in a method function. Then suppose the class gets developed and many man hours get spend on it. Then suppose way down the road some virtual aspect that is called within this function's algorithm ends up needing to change that variable when it encounters it. In that case, there is a huge amount of tracking of work and extra man hours to undo all the const 'ing that had been incorporated throughout all of the algorithms. For me in particular, I am often encountering new tasks that I would not have expected when I start writing code. Would const 'ing still be recommended even if such a case might be encountered at some point in the future? What is recommended for something along those lines?
Also, what is a mutable?
By the way, that's cool that you are a Robotics Engineer.
"well designed software architecture" is both safe and fast. You use const several different ways under different circumstances to produce safer code. You don't use const to improve software performance/speed, that's what pointers and references are for.
The idea of references is a little different. Passing by reference is used for 2 primary reasons (I know there are more, but they all boil down to these 2):
- To make code more efficient.
- To allow code to efficiently modify a value when necessary.
If you need to make the code more efficient, but you also want to make it safe, you use a const reference. A const reference is declared just like a reference except you add const to the declaration. Adding const tells the compiler that you are passing a reference, but it is not to be used to make modifications to the passed argument. If you do attempt to modify the argument/parameter, it will cause a compile error because you have written code that you have deemed illegal.
You are mixing two concepts together. You need to understand that they are two different topics with different purposes, but that they can work together.
Wow... that's a lot of questions. That's why I said "you are stepping into the realm of const-correctness", it is not a simple issue because as you said it is a way to restrict the code in a language that is built on a philosophy of freeing the code. And you exemplify very well what I was saying about "beginners" (and don't take offense, if I say so) that are not too warm to the idea of const-correctness. I will try to give some answers to your many questions:
>>I'm not seeing any more computational power coming out of it--is that correct?
Not entirely correct. There can be a speed up, but it is usually not significant in the whole scheme of things. The reason is, for the computer to use a variable, operate on it, and write it value, it has to take those step, i.e. take the variable value from the memory, do some operation with it on the CPU, and write the new value back to the memory. By a const qualifier, the compiler can omit the last operation. This is a very rough approximation of the process, and usually the processor will not do it whether the variable is const or not. But the more you tell the compiler, the better it can optimize in general. But still, I wouldn't think that the performance gain, if any, would be really measurable (I may be wrong).
>>it just make the code more readable or bug proof, right?
Well most programmers, those experienced with larger projects anyways, would say that having code that is more readable and more bug proof is by far a greater advantage than performance. So don't say "it _just_ makes the code..".
>>For clarification's sake, how is "poorly designed software architecture" defined in this case?, and how would a "well designed software architecture" be defined?
Ok, well, there are so many things that qualify software architecture as good or bad, but here is the main one, in my opinion. INDEPENDENCE, and I'm not talking about the 4th of July, this means you have atomic classes with bare minimum dependency on other parts of the software. To achieve good independence of your classes: encapsulation, abstraction and polymorphism are all geared towards that goal. Encapsulation allows the insides or guts of the class to remain inside (as it should!) and does not allow other parts of the software to temper with those internals or depend on them. Abstraction allows you to let the user forget or not care about what is inside a class and only look at the interface (including the const qualifiers which are an integral part of the interface of a class, because it defines the accessors and mutators). Finally, Polymorphism allows the rest of the software to not care about of what class an object is, only about what it does (its virtual interface, which, again, const plays a big role in). So all in all, I judge the quality of code mainly on how independent everything is in it. For example, if you draw your software architecture including all dependencies (i.e. not only class inheritance but also data member type dependence and the object graph) and if it looks like a huge spider-web, you have a poorly designed software because any changes to it will cause an echo effect. As you mentioned, when you had to change one thing, you have tons of other stuff to change, that's a big indicator of inter-dependence of the code, and thus, poor design.
>>or is there actually some more efficient use of the computer itself
somehow through a differently designed software architecture?
Well again, the performance gain is relative and relatively small. Proper software architecture has for main purpose flexibility and modularity of the code which makes the code easier to change, extend, and re-use, as well as maintain and increases longevity. But, it also can mean a certain level of performance gain since most of the time more atomic classes or self-contained classes reduce the amount of indirection (jumping from one object's method to another to another ... ). In other words, you can reduce the length of the paths followed along the object-graph. Not to mention the use of parallelism and multi-threading and other special things that are usually easier to exploit with better software design.
>>Suppose I write a class that has a const variable parameter in a method function. Then suppose the class gets developed and many man hours get spend on it. Then suppose way down the road some virtual aspect that is called within this function's algorithm ends up needing to change that variable when it encounters it.
The problem here is that you are attacking this problem in reverse. When programming object-oriented code and in group projects, your thought process needs to go the other way around. You first spend a lot of time (or man hours) thinking about the "contract", i.e. what is it that the function / class is supposed to accomplish. That's where the usual Input / Output thought process in procedural programming is now augmented with the Hold / Serve thought process. For each class you have to ask long and hard what data should it hold and what services should it provide (i.e. data members and methods). Then, for each method there needs to be lots of reflection on what data should it read, what data does it need, and what data should it output or modify (and that's where const comes in). After, the implementation can begin and your prototypes for the methods you implement become the contract, a contract you cannot break. Well, there are always exceptions, but that's the main idea to follow. If down the line you have some derived class that would need to not be const while it is being called from a virtual method from its base, which is const, then "mutable" is there to save (see below). But if you encounter a situation like this, first of all, think hard whether this is because the contract was wrong (then you might change it and it will improve the software architecture) or whether what you are doing is violating a good contract. Look up programming by contract.
>>Also, what is a mutable?
Well mutable is what I would call a last resort, as I said above, when everything else fails, mutable can save you. Actually, I never used, in fact I only learned about it a few weeks ago. After all those years, I'm happy I never had that option as a temptation to not solve my problems by proper software design. So, is you _absolutely_ need to use it, here is how and what it actually is. It simply makes a data member immune to the const qualifier, like this:
class Foo {
private:
mutable int mut_value;
int nonmut_value;
public:
int getMutValue() const { return mut_value++; }; //this will compile fine.
int getNonMutValue() const { return nonmut_value++; }; //this will NOT.
};
>>By the way, that's cool that you are a Robotics Engineer.
Yeah it is cool indeed! ;)
Thanks for the very helpful explanations. I think I'm getting it. For a particular set of classes I'm developing at the moment, their purpose is to manipulate variables. Thus, even though Net Beans defaulted to putting a const in a getter function for me, and there is a place for const types; the place for const is not in classes that are intended for changing all variables, even inside getter functions. On the other hand, const is best used in classes where the function of the class has members where read-only access is sufficient for variables of that class in those members.
It is appropriate to have const getters, you just need to call them properly.
A getter method should rarely do more than simply return some value. If there are some calculations that require temporary values, then those temporary values should be stored in local variables rather than in member variables.
Ok, now I have one more question:
Regarding the previous post about getters, it seems to me that I disagree completely about the idea of a getter not changing things. If I need to get an organized sorted list, for example, I don't want to waste any time and especially not nearly all the computer's resources for hours unless I call that function. Thus, I want my getters to change things and return a pointer and register themselves to be called when done after my thread finishes. Am I missing something here?
There are always exceptions. This is one of them. That's why I said "rarely".
Although, is it really necessary to write another method called getSortedList (or whatever you may call it)? Wouldn't it be easier to simply call object.sortList() (which by nature is non-const and I suspect you already have) then call object.getList() (which would be const and I suspect you also may already have)?
Good call--I like that point--there should be a const getter called inside any getter.
I'll have to start doing that because it will definitely help keep me more organized.
We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.