Member function still const if it calls functions that break "constness"? - c++

I'm wondering if a class's member function should be const if it calls other functions that modify its data members. A good example would be a public member function that uses private member functions to do the brunt of the work.
void Foo::Show() const { // Doesn't directly modify data members in this function
ShowPig(); // One or all of these functions modify data members
ShowCow();
ShowBar();
}
Maybe not the best example, but you get the idea.

Any Good compiler does not allow this. You should get the compiler error.

The compiler should not allow you to do that. Example below.
//MS VC 2008
class Foo
{
int m_iBar;
void ThisIsConstFunc() const
{
m_iBar = 9; //error C2166: l-value specifies const object
ThisIsNonConst(); //error C2662: 'Foo::ThisIsNonConst' : cannot convert 'this' pointer from 'const Foo' to 'Foo &'
}
void ThisIsNonConst()
{
m_iBar = 9;
}
};

If a function calls functions that modify certain data, then it should be said that the function itself modifies data. It just happens to be abstracted.
So no, that function should not be const.

C++ provides the mutable keyword for the rare case that you actually want to allow this. And there are times where it happens, for instance if your function does not change the logical state of the object, but may modify one or more members of the object.
These cases are very rare. In the vast majority of cases you should mark the member function const if neither that function nor any function it calls modifies the state of the object.

Yes, the compiler won't let you, as pointed out. Of course you can do it anyway but if the function needs to be const usually it's a bad idea. If it doesn't need to be const, don't just put it in there for no reason. There's really not much benefit to const and many potential serious problems, you just get forced into it at times.

Related

Const Member Function

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.

Passing std vector as reference: no matching function to call

I can't see what's wrong with my code. I have a an std::vector which is a private member of my class Foo. It is not declared as const, even when the error the compiler gives suggests so.
(At Foo.h)
private:
std::vector<std::string> tableBackup;
I'm calling a function (from Foo.cpp):
BackupTable(this->tableBackup);
This method is into DatabaseLoad.cpp and .h:
public:
void BackupTable(std::vector<std::string> &tableBackup);
Defined as:
void DatabaseLoad::BackupTable(std::vector<std::string> &tableBackup){
//whatever...
}
I'm getting the following error when I call the method from Foo.cpp:
No matching function for call to 'DatabaseLoad::BackupTable(const std::vector<std::basic_string<char> > &)'
What's the problem? Currently using C++11, but I guess this has nothing to do with that.
You are calling the BackupTable function in a context where the DatabaseLoad object is const-qualified, therefore the compiler is expecting a call to a const-reference.
If you are not planning on modifying the vector, you should declare the function as:
void BackupTable(const std::vector<std::string>& tableBackup);
I can guess that you are calling BackupTable from const method of Foo class
You seem to be calling BackupTable(this->tableBackup); inside a member function which is qualified as const. This means that this is of type const Whatever*, and thus all data members are implicitly const-qualified inside this member function as well. So they cannot be bound to a non-const reference.
You have two sane options:
If BackupTable does not modify its argument, it should accept it as const & instead of just &.
If it does modify its argument, it means the calling function modifies its this object, so it should not be marked as const.
A third (far less likely) option is that tableBackup is actually an implementation details of your class and the fact that it changes does not affect the "logical constness" of the class. If that is so, you can mark it as mutable (that way, even const functions will be able to modify it). At the same time, you must introduce some form of synchronisation mechanism (e.g. a mutex) whenever you access the mutable tableBackup (or any mutable member). The reason is that all of the standard library expects const operations to be thread-safe. An emerging idiom for this is adding a private member like this:
mutable std::mutex mutables;
And locking mutables whenever you access (even just for reading!) a mutable member.
I think that 'this' is const in ' BackupTable(this->tableBackup);'. You call the ' BackupTable' in a 'Foo() const' function.

Using "Static" Keyword to Limit Access in C++ Member Functions

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)

Using 'const' in class's functions [duplicate]

This question already has answers here:
Meaning of 'const' last in a function declaration of a class?
(12 answers)
Closed 5 years ago.
I've seen a lot of uses of the const keyword put after functions in classes, so i wanted to know what was it about. I read up smth at here: http://duramecho.com/ComputerInformation/WhyHowCppConst.html .
It says that const is used because the function "can attempt to alter any member variables in the object" . If this is true, then should it be used everywhere, because i don't want ANY of the member variables to be altered or changed in any way.
class Class2
{ void Method1() const;
int MemberVariable1;}
So, what is the real definition and use of const ?
A const method can be called on a const object:
class CL2
{
public:
void const_method() const;
void method();
private:
int x;
};
const CL2 co;
CL2 o;
co.const_method(); // legal
co.method(); // illegal, can't call regular method on const object
o.const_method(); // legal, can call const method on a regulard object
o.method(); // legal
Furthermore, it also tells the compiler that the const method should not be changing the state of the object and will catch those problems:
void CL2::const_method() const
{
x = 3; // illegal, can't modify a member in a const object
}
There is an exception to the above rule by using the mutable modifier, but you should first get good at const correctness before you venture into that territory.
Others have answered the technical side of your question about const member functions, but there is a bigger picture here -- and that is the idea of const correctness.
Long story short, const correctness is about clarifying and enforcing the semantics of your code. Take a simple example. Look at this function declaration:
bool DoTheThing(char* message);
Suppose someone else wrote this function and you need to call it. Do you know what DoTheThing() does to your char buffer? Maybe it just logs the message to a file, or maybe it changes the string. You can't tell what the semantics of the call are by just looking at the function declaration. If the function doesn't modify the string, then the declaration is const incorrect.
There's practical value to making your functions const correct, too. Namely, depending on the context of the call, you might not be able to call const-incorrect functions without some trickery. For example, assume that you know that DoTheThing() doesn't modify the contents of the string passed to it, and you have this code:
void MyFunction()
{
std::string msg = "Hello, const correctness";
DoTheThing(msg.c_str());
}
The above code won't compile because msg.c_str() returns a const char*. In order to get this code to compile, you would have to do something like this:
void MyFunction()
{
std::string msg = "Hello, const correctness";
DoTheThing(msg.begin());
}
...or even worse:
void MyFunction()
{
std::string msg = "Hello, const correctness";
DoTheThing(const_cast<char*>(msg.c_str()));
}
neither of which, arguably, are 'better' than the original code. But because DoTheThing() was written in a const-incorrect way, you have to bend your code around it.
The meaning is that you guarantee to clients calling a const function member that the state of the object will not change. So when you say a member function is const it means that you do not change any of the objects member variables during the function call.
const, when attached to a non-static class method, tells the compiler that your function doesn't modify the internal state of the object.
This is useful in two ways:
If you do write code that changes internal state in your const method, the compiler catches the error, moving a programming error from run-time to compile-time.
If client code calls a non-const method on a constant pointer, the compiler catches the error, ensuring the "chain of not changing things" is maintained.
Typically you want to declare all non-mutating non-static class methods as const. This allows calling code to use the const qualifier on pointers, and it helps catch mistakes.
Typical C++: you can declare a class member variable "mutable" and then change it even from a const method.
The const keyword used after a method indicate that this method doesn't modify the object on which it's called. This way, this method can be called on a const version of the object.
If this is true, then should it be used everywhere, because i don't want ANY of the member variables to be altered or changed in any way?
Well, no. Sometimes you do want instance methods to modify members. For example, any set method will obviously need to set variables, so it's not the case that you should put const everywhere. But if your object's state is totally immutable, first consider whether it might not be better to have no instances at all (i.e., a static class), and if that's not the case, then make everything const.
It's quite unusual not to want to have any member variables changed, but if that's what your class requires, then you should make all your member functions const.
However, you probably do want to change at least some members:
class A {
private:
int val;
public:
A() : val(0) {}
void Inc() { val++; }
int GetVal() const { return val; };
};
Now if I create two instances of A:
A a1;
const A a2;
I can say:
a1.GetVal();
a2.GetVal();
but I can only say:
a1.Inc();
trying to change the value of a constant object:
a2.Inc();
gives a compilation error.

What does the const operator mean when used with a method in C++?

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