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.
Related
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.
I have a C++ class like that:
class Example {
public:
int getSomeProperty(int id) const;
private:
lazilyLoadSomeData();
}
Basically getSomeProperty() return some data that has been loaded using lazilyLoadSomeData(). Since I don't want to load this data until needed, I'm calling this method within getSomeProperty()
int Example::getSomeProperty(int id) const {
lazilyLoadSomeData(); // Now the data is loaded
return loadedData[id];
}
This does not work since lazilyLoadSomeData() is not const. Even though it only changes mutable data members, the compiler won't allow it. The only two solutions I can think of are:
Load the data in the class constructor, however I do not want to do that, as lazily loading everything makes the application faster.
Make lazilyLoadSomeData() const. It would work since it only changes mutable members, but it just doesn't seem right since, from the name, the method is clearly loading something and is clearly making some changes.
Any suggestion on what would be the proper way to handle this, without having to cheat the compiler (or giving up on const-correctness altogether)?
You could make a proxy member object which you declare mutable and which encapsulates the lazy-loading policy. That proxy could itself be used from your const function. As a bonus you'll probably end up with some reusable code.
I would forward the call to a proxy object which is a mutable member of this class, something like this:
class Example {
public:
int getSomeProperty(int id) const
{
m_proxy.LazyLoad();
return m_proxy.getProperty(id);
}
private:
struct LazilyLoadableData
{
int GetProperty(int id) const;
void LazyLoad();
};
mutable LazilyLoadableData m_proxy;
};
Make lazilyLoadSomeData() const. It would work since it only changes mutable members, but it just doesn't seem right since, from the name, the method is clearly loading something and is clearly making some changes.
No, it's not making some changes, at least not from the viewpoint whoever called getSomeProperty. All changes, if you're doing it right, are purely internal, and not visible in any way from the outside. This is the solution I'd choose.
I have a class Game e.g.
class Game
{
public:
InitObjects();
...
};
And I have another class Grid, that needs to be initialised with a non-const reference to that Game object. ( A Grid object needs to call functions that can update a Game object ).
class Grid
{
public:
Grid(Game & g):
game(g){}
...
private:
Game & game;
...
};
The Game object is responsible for initialising the Grid. I did this:
void Game::InitObjects()
{
grid = new Grid(*(const_cast<Game*>(this)) );
}
grid is not a member of a Game - it's a global ( argh - i know... I don't mind making it a member, but I have the same problem right? ).
Can some seasoned C++ folk tell me if this odd looking const_cast is acceptable?
The main problem with const_cast is that it violates a promise of not causing any change to the object. It is mainly needed for interfacing with modules (C-modules?) where const isn't used consistently and you are supposed to verify whether there could be any change.
An alternative might be to have some mutable members, but of course, these should be mutable by design (like locks, caches), not by convenience (hey, I want to change this when the object issupposed to be const).
The problem with your question is that nothing is const in your question, so I don't see any need for const_cast.
I have seen more horrible things in my time without casting at all.
class A
{
private:
A * non_const_this;
public:
A() : non_const_this( this )
{
}
void changesme(); // non-const
void method() const
{
non_const_this->changesme();
}
};
The above code I have given is "I am in a non-const function now so I will grab a non-const reference to myself so I can change the object later when I need to even when I am in a const context". Which is actually worse than your possible scenario (if createObjects() is const) that is saying "This function is const because it is not changing the state now, but needs to pass out a non-const reference to self as my state will change later".
Of course better than the const modifier in the first place would be a split interface (mutable interface to an object derives from non-mutable one).
What I am looking at above is the one-to-one relationship between Game and Grid. Grid has a reference to one Game and Game's initObjects knows of one Grid. So the two are very tightly coupled. That does not necesasrily mean they should be one object - again split interface - you might want to pass a Grid& or a Game& reference for use of the interface of that class only.
Is InitObjects called from the constructor?
Given InitObjects is not const, unless you are calling InitObjects on a const Game instance, there is no need for the const_cast. I'd be vary of that circular dependency though
Construction from an object should not write to the object, so you won't be invoking UB (which you would be by writing to something that you de-consted through const_cast). However, this does look odd. Especially since Game::InitObjects() is not a const member function. Why do you think that the this pointer is const?!
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