Too much C# and too little C++ makes my mind dizzy... Could anyone remind me what this c++ declaration means? Specifically, the ending "const". Many thanks.
protected:
virtual ostream & print(ostream & os) const
A const method will simply receive a const this pointer.
In this case the this pointer will be of the const ThisClass* const type instead of the usual ThisClass* const type.
This means that member variables cannot be modified from inside a const method. Not even non-const methods can be called from such a method. However a member variable may be declared as mutable, in which case this restriction will not apply to it.
Therefore when you have a const object, the only methods that the compiler will let you call are those marked safe by the const keyword.
The ending const means that the print function shouldn't be able to change the state of any of the members of the class it is declared in (and therefore cannot call any member functions of that class which are not also declared const).
In the example below, the print function in the class Foo cannot change any of the member variables of Foo (unless they are declared mutable), and cannot call any non-const functions in Foo.
class Foo {
public:
Foo(string value) { m_value = value; }
protected:
ostream & print(ostream & os) const {
m_value = string("foobar"); // won't compile
os << m_value;
return os;
}
private:
string m_value;
};
The const on the method declaration tells the compiler that the function is safe to call on a const object of the type the function is a member of. It also signals to the compiler that the function is not supposed to alter the state of the object and it will not be able to change any member variables that are not marked as mutable.
If you omit the const, this code will not work:
const Foo bar;
bar.print(std::cout); // Will fail to compile unless 'print' is marked const
You're declaring a protected virtual method named print which takes as a parameter a reference to an ostream and returns a reference to an ostream.
The const keyword means the method won't be able to alter the state of the object, the this pointer will be const.
A virtual method is a method whose behavior can be overridden within an inheriting class, basically the virtual keyword gives C++ its' ability to support polymorphism.
And finally if you don't know what is a reference go there
Comming from C# I suppose you know what protected means :)
Related
i'm trying to understand class getters and setters functions...
My question is:
If i design a function that just only get a state from its class (a "getter" function), why mark it as "const member function"?
I mean, why use a const member function if my function is designed to not change any proprieties of its class?
i don't understand please :(
for example:
int GetValue() {return a_private_variable;}
and
int GetValue() const {return a_private_variable;}
what is the real difference?
When you declare a member function as const, like in
int GetValue() const;
then you tell the compiler that it will not modify anything in the object.
That also means you can call the member function on constant object. If you don't have the const modifier then you can't call it on an object that has been defined as const. You can still call const member functions on non-constant objects.
Also note that the const modifier is part of the member function signature, which means you can overload it with a non-const function. That is you can have
int GetValue() const;
int GetValue();
in the same class.
const can show up in three different places in C++.
Example 1:
const Object obj1;
obj1 is a const object. Meaning that you can not change anything on this object. This object can only call const member functions like
int GetValue() const {return a_private_variable;}
Example 2:
int myMethod() const {//do something}
This is a const method. It would be a const member function if it is declared inside of a class. These are the types of methods that const variables can call.
Example 3:
int myMethod(const Object &x) {//do something with x}
This is a method that takes a const parameter. This means that the logic inside myMethod is not allowed to change anything to do with x. Also note the parameter is being passed by reference not by copy. I like to think of this as a read only type of method.
When you are developing software that will be used by others; it is a good idea to not let them break things they don't know they should not break. In this case you can constrain variables, methods, and parameters to be const to guaranteed that the contract is upheld. I tried to summarize the main ideas I learned in college, but there are many resources online around const in C++. Check out this link if you would like to know more. Also it is possible that I remembered somethings incorrectly as I have not been in the C/C++ realm for a while.
A const instance of a class can only call const functions.
Having a const instance of a class is useful for making your programs more stable since then you can't modify the instance by accident.
In your case the functions do exactly the same thing, but it doesn't have to be that way.
i'm trying to understand class getters and setters functions...
My question is:
If i design a function that just only get a state from its class (a "getter" function), why mark it as "const member function"?
I mean, why use a const member function if my function is designed to not change any proprieties of its class?
i don't understand please :(
for example:
int GetValue() {return a_private_variable;}
and
int GetValue() const {return a_private_variable;}
what is the real difference?
When you declare a member function as const, like in
int GetValue() const;
then you tell the compiler that it will not modify anything in the object.
That also means you can call the member function on constant object. If you don't have the const modifier then you can't call it on an object that has been defined as const. You can still call const member functions on non-constant objects.
Also note that the const modifier is part of the member function signature, which means you can overload it with a non-const function. That is you can have
int GetValue() const;
int GetValue();
in the same class.
const can show up in three different places in C++.
Example 1:
const Object obj1;
obj1 is a const object. Meaning that you can not change anything on this object. This object can only call const member functions like
int GetValue() const {return a_private_variable;}
Example 2:
int myMethod() const {//do something}
This is a const method. It would be a const member function if it is declared inside of a class. These are the types of methods that const variables can call.
Example 3:
int myMethod(const Object &x) {//do something with x}
This is a method that takes a const parameter. This means that the logic inside myMethod is not allowed to change anything to do with x. Also note the parameter is being passed by reference not by copy. I like to think of this as a read only type of method.
When you are developing software that will be used by others; it is a good idea to not let them break things they don't know they should not break. In this case you can constrain variables, methods, and parameters to be const to guaranteed that the contract is upheld. I tried to summarize the main ideas I learned in college, but there are many resources online around const in C++. Check out this link if you would like to know more. Also it is possible that I remembered somethings incorrectly as I have not been in the C/C++ realm for a while.
A const instance of a class can only call const functions.
Having a const instance of a class is useful for making your programs more stable since then you can't modify the instance by accident.
In your case the functions do exactly the same thing, but it doesn't have to be that way.
The question: Why can a const member function sometimes modify a data member and sometimes not?
The explanation: The code below is an excerpt from working code in my baseline at work.
I have a Calculator class that owns a data member called "theLayout" (Header and Implementation defined below). The calculator class has a const member function called "Parms()" which returns a smart pointer to a Parms object that theLayout owns (by calling its own Parms() function).
The calculator class has a const member function called calculateStart() which sets (i.e. modifies) the reference returned from calling the Parms() function in the Calculator class.
This seems to contradict the meaning of const to me. If the const member function cannot modify the this pointer, then why can it set a value on one of the data members (theLayout) that it owns? Doesn't this "modify" the this pointer of the Calculator instance, and thus contradict the meaning of a const member function? Does this work because theLayout is a pointer?
Calculator Class
//Header
class Calculator
{
public:
Calculator();
//ParmsPtr is refcounted smart pointer
const ParmsPtr& parms() const {return theLayout->parms();}
protected:
void calculateStart() const; //Why does this work?
//It seems more intuitive that this should be declared as:
void calculateStart() //with no const modifier.
Layout& theLayout;
}
//Implementation
void Calculator::calculateStart() const
{
parms()->setStart(1);
}
Layout Class
//Header
class Layout : public RefCountedObject
{
public:
Layout();
//ParmsPtr is refcounted smart pointer
inline const ParmsPtr& parms() const;
private:
ParmsPtr theParms;
}
//Implementation
inline const ParmsPtr& Layout::parms() const
{
if (!theParms)
{
Layout* nonConstThis = const_cast<Layout*>(this);
ParmsPtr parms = new Parms();
nonConstThis->setParms(parms);
}
return theParms;
}
The calculator class has a const member function called calculateStart() which sets (i.e. modifies) the reference returned from calling the Parms() function in the Calculator class.
Yes, calculateStart() does modify the Calculator object, which is unexpected considering the final const qualifier in its definition.
Why ? Look at definition of inline const ParmsPtr& Layout::parms() const; the final const tells the compiler that the function will not modify the Layout object, though it actually does. How ? By mischeviously const_cast'ing the object to a non-const object; that's where the constness is broken and that's why setParms() can be called.
This is a bad practice, though there may be some reasons to do it. In such cases, const_cast serves this purpose.
The critical question is, what exactly is being made const by declaring start() to be const? The answer is the reference, not the value referenced.
In your example, inside the start() method, the compiler sees the data member as having type Layout const&, which is not the same as const Layout&. The same thing applies to pointers. If your data member was a pointer type, the compiler would see the type as Layout const*.
I couldn't understand the reason for not allowing modifiers such as const or volatile to nonmembers functions.
Following is the example code I tired
class A
{
private:
int var;
public:
int func();
};
int A::func()
{
// Some calculation on using var
int temp = var + 10;
return temp;
}
void func2( const A& tempObj ) const;
void func2( const A& tempObj )
{
std::cout << "temp obj called : " << tempObj.func() << std::endl;
}
int main()
{
A aobj;
aobj.func();
func2( aobj );
return 0;
}
which throws an compiler error error C2270: 'func2' : modifiers not allowed on nonmember functions for void func2( const A& tempObj ) const;
I also get another error error C2662: 'A::func' : cannot convert 'this' pointer from 'const A' to 'A &' for tempObj.func() in func2 here I was assuming that the member function func will be called without any errors.
const modifier states that a member function won't modify data members of the object the function belongs to.
It's like an assurance that calling that function on an object aobj won't modify the internal state of that object. So, assuming that aobj is declared const too, you will still be able to invoke that function on it; on the contrary, you would not be able to invoke non const function members.
If a function is not member of a class, it makes no sense to apply const modifier. On another language, it could have meant that the function wasn't able to modify global variables, maybe; but that language is not C++.
Imagine that there is a hidden parameter on each non-static member function:
int A::func(A* this) {...}
If you declare a member function const or volatile, that is added to that hidden parameter, pretty much like the following:
int A::func(const A* this) {...}
Some languages like python make the instance parameter on the member functions explicit, so there you write def func(self): inside a class definition to declare non-static functions.
A const qualification on a class method declares that the method doesn't modify any (non-mutable) member variables.
It therefore just doesn't make any sense to declare that on a non-member function because there are no member variables for it to modify.
The const qualification is very useful because it explicitly indicates that it's safe to call this method on a const variable without breaching the constness of that variable.
In C++, the member function modifiers apply to the object on which the function is being called. That is the use the language has for these modifiers.
Non-member functions have no such object, so the qualification would make no sense. One could imagine the language allowing cv-qualifying non-members as having no effect, but in my mind this would only be confusing. One could also imagine the cv-qualifiers having a different meaning for non-members, but the reality is what it is. That is the way the language was designed.
I have an a class which is singleton as defined follows
class myData {
private:
myData (void); // singleton class.
// Copy and assignment is prohibted.
myData (const myData &);
myData & operator=(const myData &);
static myData* s_pInstance;
public:
~myData (void);
static const myData & Instance();
static void Terminate();
void myFunc() { cout << "my function..." ;}
};
// In cpp file.
myData* myData::s_pInstance(NULL);
myData::myData(){}
myData::~myData()
{
s_pInstance = NULL;
}
const myData& myData::Instance()
{
if (s_pInstance == NULL)
{
s_pInstance = new myData();
}
return *(s_pInstance); // want to avoid pointer as user may deallocate it, so i used const referense
}
void main() {
(myData::Instance()).myFunc();
}
I am getting following error
error C2662: 'myData::myFunc' : cannot convert 'this' pointer from 'const myData' to 'myData&'
how to avoid above problem and call a function from Instance function which is returning const reference?
Thanks!
You'd want to declare func() as a constant member function, so the compiler knows it won't violate the const'd return value from the instance() function.
You could instead also make the instance() function return a 'regular' reference as apposed to a const one.
So either turn:
void myFunc() into void myFunc() const
Or turn:
const myData& myData::Instance() into myData& myData::Instance()
If you are calling a function on a const reference, the function you call must also be const, in your case void myFunc() const.
Otherwise you might return a non-const reference, if that works better.
The error says that myData::Instance() is a const instance of the class, and it can't call myFunc() on that, because myFunc() might change the instance, and you can't change a const instance.
Of course, you know that myFunc() can't really change the instance, but you must advertise this fact, as follows:
void myFunc() const { cout << "my function..." ;}
Avoiding the whole discussion of whether Singleton is a good to have pattern or the source of all evil, if you are actually implementing a singleton, chances are that const correctness will not work there as you expect it, so you should be aware of some pitfalls.
First your error: your Instance() static member returns a const reference, and that means that you can only perform operations that do not modify the object, i.e. call member functions marked as const, or use public members if present in a way that do not modify their values. My suggested solution is modify Instance() to return a non-const reference, rather than making func() const as others suggest.
Now for a longer explanation to the problem of const-correctness in general when applied to your particular Singleton problem. The basic problem is that when you implement a type, you divide those members that modify the object from those that don't, and you mark the latter as const member functions so that the compiler knows of your promise (allows you to call that method on a constant object) and helps you not break it (complains if you try to modify the state in the definition of the method). A method that is marked as const can be applied to both a constant and non constant object, but a method that is not marked const can only be applied to an object that is not const.
Back to the original piece of code, if you implement a singleton and the only way of accessing the object is by an Instance() method that returns a const reference, you are basically limiting all user code to use only const methods implemented in your interface. That means that effectively either all methods are non-mutating, or they are useless (const_cast should never be used). That in turn means that if you have any non-const operation you want to provide an Instance() method that returns a non-const reference.
You could consider implementing two variants of Instance(), but that will not be really helpful. Overload resolution will not help in user code to determine which version to use, so you will end up having to different methods: Instance(), ConstInstance() (choose your names), which means that it is up to user code to determine which one to use. The small advantage is that in their code, the choice of accessor will help documenting their intended usage, and maybe even catch some errors, but more often than not they will just call the non-const version because it works.