What is the difference betweeen something like this
friend Circle copy(const Circle &);
and something like this
friend Circle copy(Circle&) const;
I know const after the function is used to tell the compiler that this function won't attempt to change the object it is called on, what about the other one?
The first form means that the (state of the) Circle object bound to the reference which is the parameter of the copy() function will not be altered by copy() through that reference. The reference is a reference to const, so it won't be possible to invoke member functions of Circle through that reference which are not themselves qualified as const.
The second form, on the other hand, is illegal: only member functions can be const-qualified (while what you are declaring there is a global, friend function).
When const qualifies a member function, the qualification refers to the implicit this argument. In other words, that function will not be allowed to alter the state of the object it is invoked on (the object pointed to by the implicit this pointer) - with the exception of mutable objects, but that's another story.
To say it with code:
struct X
{
void foo() const // <== The implicit "this" pointer is const-qualified!
{
_x = 42; // ERROR! The "this" pointer is implicitly const
_y = 42; // OK (_y is mutable)
}
void bar(X& obj) const // <== The implicit "this" pointer is const-qualified!
{
obj._x = 42; // OK! obj is a reference to non-const
_x = 42; // ERROR! The "this" pointer is implicitly const
}
void bar(X const& obj) // <== The implicit "this" pointer is NOT const-qualified!
{
obj._x = 42; // ERROR! obj is a reference to const
obj._y = 42; // OK! obj is a reference to const, but _y is mutable
_x = 42; // OK! The "this" pointer is implicitly non-const
}
int _x;
mutable int _y;
};
C++ class methods have an implicit this parameter which comes before all the explicit ones. So a function declared within a class like this:
class C {
void f(int x);
You can imagine really looks like this:
void f(C* this, int x);
Now, if you declare it this way:
void f(int x) const;
It's as if you wrote this:
void f(const C* this, int x);
That is, the trailing const makes the this parameter const, meaning that you can invoke the method on const objects of the class type, and that the method cannot modify the object on which it was invoked (at least, not via the normal channels).
LET'S CLEAR ALL CONFUSION RELATED TO const
const came from constant mean something is not changeable but readable.
if we qualify our variable with const keyword ,we can't change it later.
e.g.
constint var =25; const variable must be initialized when it's declared.
var =50; // gives error
if we qualify our pointer variable with const after * then we can't change pointer itself but content of pointer is changeable.
e.g.
int *const ptr = new int;
ptr = new int; //gives error
// but
*ptr=5445; //allowed
if we qualify our pointer variable with const before * then we can change pointer itself but content of pointer is not changeable.
e.g.
intconst* ptr = new int(85);
//or
constint * ptr = new int(85);
ptr = new int; // allowed
// but
*ptr=5445; // gives error
pointer and content both constant
e.g.
intconst*constptr = new int(85);
//or
constint *constptr = new int(85);
ptr = new int; // not allowed
*ptr=5445; // not allowed
Circle copy(const Circle &);
here const Circle means value of Circle is only readable ,if we try to change value of Circle inside function then it gives error.
friend Circle copy(Circle&) const;
This type of function is not for non member variable .it is used for class or structure.
Here whole function is qualified with const keyword means we can't change object member variable .
e.g
class A{ public :
int var;
void fun1()
{ var = 50; // allowed
}
void fun2()const
{ var=50; //not allowed
}
};
Circle copy(Circle&) const;
makes the function const itself. This can only be used for member functions of a class/struct.
Making a member function const means that
it cannot call any non-const member functions
it cannot change any member variables.
it can be called by a const object(const objects can only call const functions). Non-const objects can also call a const function.
It must be member function of the class 'Circle'.
Now consider the next one:
Circle copy(const Circle &);
while this one means that the parameter passed cannot be changed within the function. It may or may not be a member function of the class.
NOTE: It is possible to overload a function in such a way to have a const and non-const version of the same function.
One refers to the parameter the other to the function.
Circle copy(const Circle &);
This means that the parameter passed in cannot be changed within the function
Circle copy(Circle&) const;
The const qualified function is used for member functions and means you cannot change the data members of the object itself. The example you posted was nonsensical.
Read right-to-left
If we rewrite the first function as Circle copy(Circle const&);, which means the same thing, it becomes clear that reading right to left becomes useful. copy is a function that takes a const reference to a Circle object and returns a Circle object by reference.
friend Circle copy(const Circle &);//refers to constant parameter of the function. cant' change the value stored by parameter.
Need to remove friend in your example
Circle copy(Circle&) const;
//can't change this poniter value named as Constant member function
friend Circle copy(const Circle &);
The value of parameter will not be changed during the function calls.
friend Circle copy(const Circle &)const ;
The function is an accessor that does not change any value of class members. Generally, there are to types of functions: accessors and mutators.
Accessor: examines but does not change the state of its object.
Related
A co-worker asked about some code like this that originally had templates in it.
I have removed the templates, but the core question remains: why does this compile OK?
#include <iostream>
class X
{
public:
void foo() { std::cout << "Here\n"; }
};
typedef void (X::*XFUNC)() ;
class CX
{
public:
explicit CX(X& t, XFUNC xF) : object(t), F(xF) {}
void execute() const { (object.*F)(); }
private:
X& object;
XFUNC F;
};
int main(int argc, char* argv[])
{
X x;
const CX cx(x,&X::foo);
cx.execute();
return 0;
}
Given that CX is a const object, and its member function execute is const, therefore inside CX::execute the this pointer is const.
But I am able to call a non-const member function through a member function pointer.
Are member function pointers a documented hole in the const-ness of the world?
What (presumably obvious to others) issue have we missed?
The constness of execute() only affects the this pointer of the class. It makes the type of this a const T* instead of just T*. This is not a 'deep' const though - it only means the members themselves cannot be changed, but anything they point to or reference still can. Your object member already cannot be changed, because references cannot be re-seated to point to anything else. Similarly, you're not changing the F member, just dereferencing it as a member function pointer. So this is all allowed, and OK.
The fact that you make your instance of CX const doesn't change anything: again, that refers to the immediate members not being allowed to be modified, but again anything they point to still can. You can still call const member functions on const objects so no change there.
To illustrate:
class MyClass
{
public:
/* ... */
int* p;
void f() const
{
// member p becomes: int* const p
*p = 5; // not changing p itself, only the thing it points to - allowed
p = NULL; // changing content of p in const function - not allowed
}
};
In this context object is a reference to a X, not a reference to a const X. The const qualifier would be applied to the member (i.e. the reference, but references can't be const), not to the referenced object.
If you change your class definition to not using a reference:
// ...
private:
X object;
// ...
you get the error you are expecting.
The instance object of class X is not const. It is merely referenced by an object which is const. Const-ness recursively applies to subobjects, not to referenced objects.
By the alternative logic, a const method wouldn't be able to modify anything. That is called a "pure function," a concept which doesn't exist in current standard C++.
You are calling foo on object, not on this.
Since object is declared as an X&, in a constant CX, it is actually an X& const (which is not the same as const X&) allowing you to call non const methods on it.
One helpful way of thinking about it might be that your X object is not a member of CX at all.
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*.
If we have a function prototype like this :
const CString function(...)
{
CString x;
//do some stuff
return x;
}
does this mean that function returns a const CString ? because const in C++ can be placed in front of a method inside a class to tell the compiler that the attributes will not be modified (or not mutable)
I ask this "dumb" question, because in another case we can have something like this :
static CString function(...)
{ }
And in this case static relates to "function" and not to the variable returned.
In C++ const return_type function_name(params) means you have a function that returns a const return_type. If you have static return_type function_name(params) then this marks the function as static and you no longer need an instance of the class to call this function. If you want to mark a function as const meaning that it will not moodify the class contents then you need to place the const after the function as
return_type function_name(params) const
^^^^^
does this mean that function returns a const CString ?
Yes it does.
because const in C++ can be placed in front of a method inside a class to tell the compiler that the attributes will not be modified (or not mutable)
No it can't, the const has to be placed after the method to achieve that.
class MyClass {
// ...
const CString function();
// ...
}
A function returning const CString.
class MyClass {
// ...
CString const function();
// ...
}
Same thing.
class MyClass {
// ...
CString function() const;
// ...
}
A function that can be called on a constant object, as it "promises" not to change internal state.
As a rule of thumb, const is always after the thing declared constant...
...except for the old C-style const <type>, kept for backward compatibility.
The following two lines are the same thing, a constant pointer to a constant int. Note that to make the pointer constant, the const has to be trailing the *:
const int * const p1; // the exception
int const * const p2;
To return a const value from a function use :
const CString function(...)
{
CString x;
//do some stuff
return x;
}
To tell the compilater that attributes won't change use :
CString myClass::function(...) const
{
CString x;
//do some stuff
return x;
}
const CString function(...) returns a const CString,
but it is deprecated as rarely useful and by the fact that disallows move on the temporary. So, in CString s; s = foo();, a copy is done instead of a move.
The most significant usage was to forbid things like
foo() = CString(..);
C++11 introduces ref qualifier on method and r-value reference which allows to fix that differently:
Obj& operator = (const Obj& rhs) & ; // Note the final &
A function declared as const CString function(...) returns a const CString. This the the same in C++ as it is in C.
If you have a C++ method defined like this:
void MyClass::function(void) cont;
That means that the method function does not modify the object.
const appearing before the method describes the attributes of the return type of the method.
So,
const CString method_name();
means that the method returns a const CString object i.e. an object that cannot be modified by the caller of this method.
const appearing after the method describes the attributes of the method itself. It tells that the method does not "mutate" or "modify" the object it operates on.
So,
const CString method_name() const;
means that the method cannot modify any of the member variables of the object used to invoke the method. It has no relation with the return type of the method.
Let us see this with an example.
class Foo
{
int x;
int GetX() const {return x;}
void SetX(int i_x) {x = i_x;}
};
In the above class definition, GetX() is a const method i.e. it is not expected to modify the object which is used to invoke them. What does this mean? When you declare a class, there is a single version of each of the member functions which gets loaded onto memory. Further, all the non-static member methods need an object to invoke them. How is this achieved? When you declare a non-static member method of the class, the C++ compiler slyly changes the signature of the methods to expect a "this" pointer, that is the pointer to the object used to invoke the method.
For a non-const method, the type of the "this" pointer expected is Class*. So our SetX() method above looks like:
void SetX(Foo* this, int i_x) {this->x = i_x;}
You can use the this pointer to modify the object(x is part of the object right!)
However, for a const method, the type of the "this" pointer passed is
const Class* i.e. you cannot modify the object using the "this" pointer. So GetX becomes
int GetX(const Foo* this) {return this->x; }
Since the type of the this pointer is const Foo*, you cannot change the object the pointer points to i.e. you cannot do someething like:
x = 100;
which would translate to this->x = 100; which the compiler will complain about.
The assignment is to create a constant function getArea() that returns the area of a rectangle.
double getArea() {
return width * height;
}
Is this it?
Do I put const after the parameters?
I don't really understand what I'm being asked.
In C++, a function becomes const when const keyword is used in function’s declaration. The idea of const functions is not allow them to modify the object on which they are called.
double getArea() const {
return width * height;
}
const after the (empty) argument list in the function declarations. indicates that getArea() function do not modify the state of a object i.e. data member of a object.
Please refer this link for more explanation: http://www.codeproject.com/Articles/389602/Constant-Member-Functions-Are-Not-Always-Constant
double getArea() const
{
return width * height;
}
const keyword is used when the user doesnt want to modify or change the values of that variable or function.
Just like the built-in data types (int, double, char, etc…), class objects can be made const by using the const keyword. All const variables must be initialized at time of creation.
Once a const class object has been initialized via constructor, any attempt to modify the member variables of the object is disallowed, as it would violate the constness of the object. This includes both changing member variables directly (if they are public), or calling member functions that sets the value of member variables.
const class objects can only call const member functions. A const member function is a member function that guarantees it will not change any class variables or call any non-const member functions.
SOURCE : leancpp.com
Consider:
class ClassType
{
int x;
public:
ClassType(int _x) : x(_x) {}
int GetX() { return x;}
};
const ClassType object(20);
object.GetX();
This will fail to compile, since the object is const (readonly). But GetX is not marked const (readonly). length(), size(), IsOpen() are example of methods that may be called from a read only object. Hence the class should facilitate such (const) functions for const object.
You generally don't create const object, but you do pass them like:
void foo(const ClassType& obj);
Therefore, the GetX function should be:
int GetX() const { return x;}
const make a promise or a contract that this function doesn't modify this object.
A co-worker asked about some code like this that originally had templates in it.
I have removed the templates, but the core question remains: why does this compile OK?
#include <iostream>
class X
{
public:
void foo() { std::cout << "Here\n"; }
};
typedef void (X::*XFUNC)() ;
class CX
{
public:
explicit CX(X& t, XFUNC xF) : object(t), F(xF) {}
void execute() const { (object.*F)(); }
private:
X& object;
XFUNC F;
};
int main(int argc, char* argv[])
{
X x;
const CX cx(x,&X::foo);
cx.execute();
return 0;
}
Given that CX is a const object, and its member function execute is const, therefore inside CX::execute the this pointer is const.
But I am able to call a non-const member function through a member function pointer.
Are member function pointers a documented hole in the const-ness of the world?
What (presumably obvious to others) issue have we missed?
The constness of execute() only affects the this pointer of the class. It makes the type of this a const T* instead of just T*. This is not a 'deep' const though - it only means the members themselves cannot be changed, but anything they point to or reference still can. Your object member already cannot be changed, because references cannot be re-seated to point to anything else. Similarly, you're not changing the F member, just dereferencing it as a member function pointer. So this is all allowed, and OK.
The fact that you make your instance of CX const doesn't change anything: again, that refers to the immediate members not being allowed to be modified, but again anything they point to still can. You can still call const member functions on const objects so no change there.
To illustrate:
class MyClass
{
public:
/* ... */
int* p;
void f() const
{
// member p becomes: int* const p
*p = 5; // not changing p itself, only the thing it points to - allowed
p = NULL; // changing content of p in const function - not allowed
}
};
In this context object is a reference to a X, not a reference to a const X. The const qualifier would be applied to the member (i.e. the reference, but references can't be const), not to the referenced object.
If you change your class definition to not using a reference:
// ...
private:
X object;
// ...
you get the error you are expecting.
The instance object of class X is not const. It is merely referenced by an object which is const. Const-ness recursively applies to subobjects, not to referenced objects.
By the alternative logic, a const method wouldn't be able to modify anything. That is called a "pure function," a concept which doesn't exist in current standard C++.
You are calling foo on object, not on this.
Since object is declared as an X&, in a constant CX, it is actually an X& const (which is not the same as const X&) allowing you to call non const methods on it.
One helpful way of thinking about it might be that your X object is not a member of CX at all.