Suppose I have a class with a member variable that I don't want to be changed. Is there any difference between making that variable a private const and just making the variable private, assuming there is no setter function?
Private:
class ConstFoo
{
public:
Foo(int a);
virtual ~Foo();
int val(){ return val_; }
private:
int val_;
}
Private Const:
class ConstFoo
{
public:
Foo(int a);
virtual ~Foo();
int val(){ return val_; }
private:
const int val_;
}
It seems that there is no difference between the two, since you can't change the value of val_ in either case, so the const qualifier seems redundant.
The one reason I can see to explicitly add const is for code clarity, so people working on the code in the future don't add a setter to the function. However, with the name as ConstFoo and documentation specifically stating that it is not meant to be mutable, I don't think this will be an issue.
It's all a matter of how "const" you want this value to be.
As it currently stands, no external user can directly change the value. But they can do so indirectly, because the object itself may not be const:
ConstFoo a{0};
ConstFoo b{2};
a = b;
a now has 2 in it.
Plus, code within ConstFoo can change its value too; this is why the copy assignment operator can change its value.
So if you want to ensure that the specific member object will assume one value throughout the lifetime of any ConstFoo instance, you declare it const.
Of course, this makes ConstFoo non-assignable.
You correct that no outsider can change the member if it is private. This does not mean though that it can't be changed. If you had another member function like
void bar() { val_ = 42; }
Then your first code block would compile while the second one would give you an error. If you truly do not want to be able to change the value of the member then it should be const regardless if it is private or not. That const will act as a bug checker for you.
You've pretty much answered it yourself: making it const expresses your intention very clearly, and give the compiler the ability to back you up.
In my humble opinion, the const keyword serves two purposes:
A) It shows the programmers intent that this value is not to be changed once it's been set,
B) It allows the compiler to enforce that intent, thereby preventing mistakes.
Naming it constFoo somewhat achieves the first of these but does nothing for the second. And is (again IMHO) significantly more ugly than using const.
Not sure, if i get your question right, but generally speaking:
private members can only be accessed from inside the class itself, whereas public members can be accessed from the outside
const members can only be set once inside the constructor when creating a new object of this specific class
That means, a private const variable could be set once when creating a new object of this class and could therefor act as an internal modifier (e.g. giving a offset to certain functions provided by that class) valid over the whole lifetime of this object.
A mere private variable could change its value from inside the class and therefor.
Also generally speaking you are completely right, the whole concept of using constants in C++ is for making sure, your constraints are complied to in the further development process (not only by other developers, also by yourself)
The private keyword makes sure noone outside the class can modify the variable.
If you don't modify the variable inside the class then the result is the same.
As my opinion it is better to use the keywork const too because not only it is telling to the developers (including yourself) who might modify your class that it is intended to remain constant but it is also more secure: if they try modify the modification will not have effect.
So in my opinion it is not redundant.
Related
We know that const object members cannot be modified once declared but what is the real use of them? We can individually declare variables to be const inside the class or declare them private.
If there is any other significance of const object in C++, then please mention that too.
To answer your question literally:
If you make members of a class const, that applies to every instance of the class, but only to the members that you made const.
If you make an object const, that applies to a single instance of that class, but it does apply to all members of that instance.
const is one of the most elementary subjects in C++, in my opinion. Something that is way too often overlooked.
Generally const has three use cases:
Allowing the compiler to optimize more aggressively
Allowing the compiler to point out our mistakes when we accidentally try to change a const value
Convey intend by specifying that we do not want an object changed
In the case of a const member of a class, we force the object to be initialized during instantiation of the class. Preventing us from accidentally changing it's value in member functions. Which is the big difference to just using a private member variable. We still can accidentally change a private member variable anywhere inside the class.
One of the most useful ways to use const is with parameters:
This can allow major optimization for the compiler, for various reasons that are out of scope of this answer.
And in the case of const references, the compiler can prevent you from accidentally changing the value of that reference.
Most importantly, it allows you to define the signature of your function in a more clarifying way.
I luckily use this once(so far). And i never thought i would need to use a const in a member variable.
class TypeA {
protected:
DataX const* m_data; //get a pointer to a data that shouldn't be modified even inside the class.
public:
TypeA(DataX const* p){
m_data = p;
}
auto& getData(){ return *m_data; } //will return DataX const&
}
For the private member variables, i think they are best for helper-variables in the current class that are really not part of the object logically. Maybe for caching, temporary holder of some data that should be there for a time duration, a counter for an algorithm, etc. And they are only used and should be used in the current class. You don't want other programmers to use them in the derived class because they have a very special use so you hide them in private.
Another example for const member are for constant values aside for enums. I prefer enum over a variable that takes storage but some programmer prefer following on what they used to however you convinced them not to(maybe i'm wrong, and they are really correct, and maybe in the future for some reason the const in the language changed, and then using const might be better.)
class TypeA {
public:
const int HEY_VALUE = 101;
const int YOH_VALUE = 102;
const int HELP_VALUE = 911;
const float MIN_SOMETHING = 0.01;
static const int HELLO_EARTH = 10;
//...
}
I can't find this specific code of mine, but i think i used & instead of const*. I used it like this.
class TypeA {
protected:
DataX& m_data;
public:
TypeA(DataX& p):m_data(p){ //you can only set this once in the constructor
}
auto& getData(){ return m_data; } //will return DataX const&
}
I really prefer using . instead of -> for personal reasons so I really pushing myself to achieve the syntax i want and i came with these weird solutions. It's fun because I discovered that those weird approaches are still valid and achievable in c++.
Update
If there is any other significance of const object in C++, then please mention that too.
Maybe you can const some filler bytes on specific part of the class.
class TypeA {
protected:
const int HEADER_BYTES = 0x00616263;
int m_data1;
int m_data2;
const uint8_t ANOTHER_FILLER_FOR_SOME_REASON = 0xffffffff; //maybe forcing offset address, or alignment, etc.
int m_anotherData;
}
Generally, const keyword is being used to improve readability of the code you are writing.
However, in some cases const can also allow compiler optimizations. Let's see the following code snippet:
int const i = 1;
fun(&i);
printf("%d\n", i);
Here, trying to modify the variable i would cause an Undefined Behaviour. Therefore, the compiler will assume modification won't be even tried so it will pass the value 1 to the printf function.
Same is valid for const data members.
Well, I know the functionality of const data member in a C++ class.
What I want to know is, the purpose of introducing a const data member in a class. Why someone will use that while writing a real software? What are the real-life usage of const data members?
Please give me a few real life examples with reasons.
EDIT :
I am not asking about static const data member.
I am asking for some real life use cases where each object will be having a different const value for same data.
You'd use a const data member for the same reason that you'd use any const object: for a value that may be arbitrarily initialised but then never changed.
A good rule of thumb is to denote something as const "by default", so you can picture plenty of reasons to use it in a class.
class User
{
User(const std::string& name)
: name(name)
{}
private:
/**
* User's name is an invariant for the lifetime of this object.
*/
const std::string name;
};
Can you leave out the const here? Yeah, sure. But then you may accidentally change name when you didn't mean to. The entire purpose of const is to protect against such accidents.
However, sadly, your class will not be assignable!
There are several cases. The most obvious one is a static const data member. These are used as scoped constants:
class Something {
static const int SOME_CONSTANT = 17;
};
Note that under C++11 and onward, constexpr usually makes more sense in those cases.
This defines a constant that is typed and scoped to the class' implementation. I suspect this was not what you were asking, however.
The more interesting use case is for values that are different between instances of the class, but constant across the class' lifetime.
For example, suppose you have a RAID implementation, where a configuration sets the stripe width. You do not know the stripe width at compile time, so the above construct will not help you. You do want the width to remain constant throughout the class' lifetime however (maybe your code doesn't know how to handle stripe width changes).
In those cases, marking the value const, and setting it in the constructor, can give you compile time guarantee that no one is changing this value.
You use it exactly the same as you would use a globally declared const, only you want it to only apply to the class you have defined it in. For example
class Character
{
public:
Character()
:
mCurrentHealth{TOTAL_HEALTH},
mCurrentMana{TOTAL_MANA}
{
}
// Define lose/gain health/mana functions
// for mCurrentHealth and mCurrentMana
private:
int mCurrentHealth;
int mCurrentMana;
// Constants
const int TOTAL_HEALTH = 100;
const int TOTAL_MANA = 50;
};
There are many other examples, but the main point is that we don't want TOTAL_HEALTH and TOTAL_MANA defined outside the class, because they won't be relevant.
The const member function guarantees that no member variables can be changed by the member function unless they are marked as mutable.
That being said it guarantees nothing else?
Here is a real example. I have a classes EventHandler and EventDispatcher.
class EventHandler
{
public:
void registerHandler(EventHandler* handler) const // Should this be a const?
{
EventDispatcher::registerHandler(handler);
}
};
EventDispatcher // Singleton Class
{
public:
void registerHandler(EventHandler* handler)
{
mListeners.push_back(handler);
}
private:
std::vector<EventHandler*> mListeners;
};
Should EventDispatcher's registerHandler(EventHandler*) be const? It does not change its member variables, but it does change global state.
Correct, it makes no guarantees about any other state than the object itself. And I would say that there's no particular requirement that it doesn't modify global state. [If you take it to extremes, any function call does modify the current state of the processor - even if it's just storing the return address on the stack [1]].
But a more reasonable thing would be that a const member function like this:
class myclass
{
private:
std::vector<int> v;
public:
std::vector<int> getV() const { return v; }
};
This will create a copy of the vector v - which in turn allocates memory (thus changing global state). An output function that feeds your object to a output stream would be a similar thing.
If a member function modifies some global state (in a way that isn't obvious), then it probably should be made clear in the description of the function (documentation is useful sometimes).
[1] Of course, the C++ and C standards do not state that the processor has to have a stack, return addresses, etc - the compiler could inline all the code, and not make any "calls" at all, or use magic to "remember" where to get back to - as long as the magic actually works, it's fine to rely on that.
Edit based on your edited question:
It's one of those that isn't entirely obvious in either direction, you would expect the registerHanlder to do something like "store the handler object somewhere". But since it's not modifiying the object itself, it may help to explain that it's updating the dispatcher class. Of course, if it's not actually updating the class itself, or using anything from the class, you probably should make it static rather than const - that way it's clear that it's not actually modifying the object itself.
Aside: As it is written, your code won't work, since EventDispatcher::registerHandler is not a static member, and your EventHandler::registerHandler is not referring to an instance of EventDispatcher. You would either have to make an instance of EventDispatcher as a global variable, or make EventDispatcher::registerHandler a static function and make mListeners a static member. Or something else along those lines.
What does the const keyword behind a method declaration guarantee?
The guaranty is a contractual reminder, rather than 'physical' memory barrier.
Thus, if you implement the const keyword correctly, the compiler will be able to help you to detect possible bugs.
However, no C/C++ compiler will stop you from modifying the member state directly; neither via fields nor by casting the object reference to a pointer and modifying the underlying memory.
Is my const method allowed to change (local/global) state?
A const method is not allowed to change the external behaviour of the system, but it is perfectly acceptable for a const method to change the internal state.
In other words, after calling all const methods randomly a couple of times, the system should still provide the same behaviour it did initially.
On the other hand, if the const method feels like caching a time consuming calculation and reuse it for the next call, it should be allowed. Same goes for a logger class that logs statistics, but does not change the behaviour of the system.
I understand that one benefit of having static member functions is not having to initialize a class to use them. It seems to me that another advantage of them might be not having direct access to the class's not-static stuff.
For example a common practice is if you know that a function will have arguments that are not to be changed, to simply mark these constant. e.g.:
bool My_Class::do_stuff(const int not_to_be_changed_1,
std::vector<int> const * const not_to_be_changed_2)
{
//I can't change my int var, my vector pointer, or the ints inside it.
}
So is it valid to use static member functions to limit access. For example, lets say you have a function
void My_Class::print_error(const unsigned int error_no) {
switch (error_no) {
case 1:
std::cout << "Bad read on..." << std::endl;
break;
//...
default:
break;
}
}
Well here we're not going to be accessing any member variables of the class. So if I changed the function to:
static void My_Class::print_error(const unsigned int error_no) {
switch (error_no) {
case 1:
std::cout << "Bad read on..." << std::endl;
break;
//...
default:
break;
}
}
I'd now get an error, if I inadvertently tried to access one of my private var, etc. (unless I pass myself an instance of my class, which would be purposeful ^_^ !)
Is this a valid technique, similar to proactively making args that should not be changed constants?
What downsides might it have in terms of efficiency or use?
My chief reason for asking is that most of the "static" tutorials I read made no mention of using it in this way, so I was wondering if there was a good reason why not to, considering it seems like a useful tool.
Edit 1: A further logical justification of this use:
I have a function print_error,as outlined above. I could use a namespace:
namespace MY_SPACE {
static void print_error(...) {
...
}
class My_Class {
....
void a(void)
}
}
But this is a pain, because I now have to lengthen ALL of my var declarations, i.e.
MY_SPACE::My_Class class_1;
all to remove a function from my class, that essentially is a member of my class.
Of course there's multiple levels of access control for functions:
//can't change pointer to list directly
void My_Class::print_error(std::vector<int> const * error_code_list) {...}
//can't change pointer to list or list members directly
void My_Class::print_error(std::vector<int> const * const error_code_list) {...}
//can't change pointer to list or list members directly, access
//non-const member vars/functions
void My_Class::print_error(std::vector<int> const * const error_code_list) const {...}
//can't change pointer to list or list members directly, access
//non-static member vars/functions
static void My_Class::print_error(std::vector<int> const * const error_code_list) {...}
//can't change pointer to list or list members directly, access
//member vars/functions that are not BOTH static and const
static void My_Class::print_error(std::vector<int> const * const error_code_list) const {...}
Sure this is a bit atypical, but to lessening degrees so are using const functions and const variables. I've seen lots of examples where people could have used a const function, but didn't. Yet some people think its a good idea. I know a lot of beginning c++ programmers who wouldn't understand the implications of a const function or a static one. Likewise a lot would understand both.
So why are some people so adamantly against using this as an access control mechanism if the language/spec provides for it to be used as such, just as it does with const functions, etc.?
Any member function should have access to the other members of the object. Why are you trying to protect yourself from yourself?
Static members are generally used sparingly, factory methods for example. You'll be creating a situation that makes the next person to work with your code go "WTF???"
Don't do this. Using static as an access-control mechanism is a barbaric abomination.
One reason not to do this is because it's odd. Maintenance programmers will have a hard time understanding your code because it's so odd. Maintainable code is good code. Everybody gets const methods. Nobody gets static-as-const. The best documentation for your code is the code itself. Self-documenting code is a goal you should aspire to. Not so that you don't have to write comments, but so that they won't have to read them. Because you know they're not going to anyway.
Another reason not to do this is because you never know what the future will bring. Your print_error method above does not need to access the class' state -- now. But I can see how it one day might need to. Suppose your class is a wrapper around a UDP socket. Sometime in the middle of the session, the other end slams the door. You want to know why. The last messages you sent or received might hold a clue. Shouldn't you dump it? You need state for that.
A false reason to do this is because it provides member access control. Yes it does this, but there are already mechanisms for this. Suppose you're writing a function that you want to be sure doesn't change the state of the object. For instance, print_error shouldn't change any of the object's state. So make the method const:
class MyClass
{
public:
void print_error(const unsigned int error_no) const;
};
...
void MyClass::print_error(const unsigned int error_no) const
{
// do stuff
}
print_error is a const method, meaning effectively that the this pointer is const. You can't change any non-mutable members, and you can't call any non-const methods. Isn't this really what you want?
Static member functions should be used when they are relevant to the class but do not operate on an instance of the class.
Examples include a class of utility methods, all of which are static because you never need an actual instance of the utility class itself.
Another example is a class that uses static helper functions, and those functions are useful enough for other functions outside the class.
It is certainly fair to say that global scope functions, static member functions, and friend functions aren't quite orthogonal to one another. To a certain extent, this is largely because they are intended to have somewhat different semantic meaning to the programmer, even though they produce similar output.
In particular, the only difference between a static member method and a friend function is that the namespaces are different, the static member has a namespace of ::className::methodName and the friend function is just ::friendFunctionName. They both operate in the same way.
Well, actually there is one other difference, static methods can be accessed via pointer indirection, which can be useful in the case of polymorphic classes.
So the question is, does the function belong as "part" of the class? if so, use a static method. if not, put the method in the global scope, and make it a friend if it might need access to the private member variables (or don't if it doesn't)
Given a declaration like this:
class A {
public:
void Foo() const;
};
What does it mean?
Google turns up this:
Member functions should be declared with the const keyword after them if they can operate on a const (this) object. If the function is not declared const, in can not be applied to a const object, and the compiler will give an error message.
But I find that somewhat confusing; can anyone out there put it in better terms?
Thanks.
Consider a variation of your class A.
class A {
public:
void Foo() const;
void Moo();
private:
int m_nState; // Could add mutable keyword if desired
int GetState() const { return m_nState; }
void SetState(int val) { m_nState = val; }
};
const A *A1 = new A();
A *A2 = new A();
A1->Foo(); // OK
A2->Foo(); // OK
A1->Moo(); // Error - Not allowed to call non-const function on const object instance
A2->Moo(); // OK
The const keyword on a function declaration indicates to the compiler that the function is contractually obligated not to modify the state of A. Thus you are unable to call non-const functions within A::Foo nor change the value of member variables.
To illustrate, Foo() may not invoke A::SetState as it is declared non-const, A::GetState however is ok because it is explicitly declared const. The member m_nState may not be changed either unless declared with the keyword mutable.
One example of this usage of const is for 'getter' functions to obtain the value of member variables.
#1800 Information: I forgot about mutable!
The mutable keyword instructs the compiler to accept modifications to the member variable which would otherwise cause a compiler error. It is used when the function needs to modify state but the object is considered logically consistent (constant) regardless of the modification.
This is not an answer, just a side comment. It is highly recommended to declare variables and constants const as much as possible.
This communicates your intent to users of your class (even/especially yourself).
The compiler will keep you honest to those intentions. -- i.e., it's like compiler checked documentation.
By definition, this prevents state changes you weren't expecting and can, possibly, allow you to make reasonable assumptions while in your methods.
const has a funny way of propagating through your code. Thus, it's a really good idea to start using const as early and as often as possible. Deciding to start const-ifying your code late in the game can be painful (easy, but annoying).
If you're using a language with static, compile time checks it's a great idea to make as much use of them as possible... it's just another kind of testing really.
Functions with const qualifier are not allowed to modify any member variables. For example:
class A
{
int x;
mutable int y;
void f() const
{
x = 1; // error
y = 1; // ok because y is mutable
}
};
C++ objects can be declared to be const:
const A obj = new A();
When an object is const, the only member functions that can be called on that object are functions declared to be const. Making an object const can be interpreted as making the object readonly. A const object cannot be changed, i.e. no data members of the object can be changed. Declaring a member function const means that the function is not allowed to make any changes to the data members of the object.
Two suggested best practices from experience:
(1) Declare const functions whenever possible. At first, I found this to be just extra work, but then I started passing my objects to functions with signatures like f(const Object& o), and suddenly the compiler barfed on a line in f such as o.GetAValue(), because I hadn't marked GetAValue as a const function. This can surprise you especially when you subclass something and don't mark your version of the virtual methods as const - in that case the compile could fail on some function you've never heard of before that was written for the base class.
(2) Avoid mutable variables when it's practical. A tempting trap can be to allow read operations to alter state, such as if you're building a "smart" object that does lazy or asynchronous i/o operations. If you can manage this with only one small mutable variable (like a bool), then, in my experience, this makes sense. However, if you find yourself marking every member variable as mutable in order to keep some operations const, you're defeating the purpose of the const keyword. What can go wrong is that a function which thinks it's not altering your class (since it only calls const methods) my invoke a bug in your code, and it could take a lot of effort to even realize this bug is in your class, since the other coder (rightly) assumes your data is const because he or she is only calling const methods.
const has a funny way of propagating through your code. Thus, it's a really good idea to start using const as early and as often as possible. Deciding to start const-ifying your code late in the game can be painful (easy, but annoying).
Additionally, you will easily run into problems if methods that should be const aren't! This will creep through the code as well, and make it worse and worse.
that will cause the method to not be able to alter any member variables of the object