How this code modifies a value in a const function:
#include<iostream>
using namespace std;
class Y;
class X{
public:
void access(Y &y) const;
};
class Y{
int d;
public:
friend void X::access(Y &y) const;
Y(){d=0;}
};
void X::access(Y &y) const
{
cout<<"Y is "<<y.d<<endl;
y.d=1;
cout<<"Y is "<<y.d<<endl;
}
int main() {
X x;
Y y;
x.access(y);
}
And this code gives an error:
#include<iostream>
using namespace std;
class Y{
int d;
public:
void set() const{d=0;}
};
int main() {
Y y1;
return 0;
}
Because in your first example:
void X::access(Y &y) const;
the const tells the compiler that the function won't modify the class X object that the implicit this parameter points to. The class Y object that's passed as a reference isn't const.
In the second example, the set() function is a member of class Y:
void set() const
and it's declared such that the implicit this parameter pointing to the Y object is a const pointer (so that object can't be modified).
If you want X::access() to not be permitted to modify the Y object passed to it, change the declaration to:
void X::access(Y const& y) const;
Because inside a const function, only *this is const, not the parameters passed to the function or anything else.
In the first example, the const-qualifier on X::access(Y &y) const means that the X object on which it is called cannot be modified. Since the Y parameter is taken by non-const reference, it can be modified from within the function.
In the second example, the const-qualifier on Y::set() const means that the Y object on which it is called cannot be modified, hence why you cannot modify the non-mutable member variable d.
a member function being const only promises not to change any members of the class it belongs to (execpt if they are declared mutable).
In the first example, Y.d is being modified in method X::access. The method does not modify any members of X itself so is perfectly sane.
In the second example however, the Y::set() method is declared const so it cannot change Y::d.
Next time, please post the code here instead of providing a link.
Related
I am working on const-correctness of my code and just wondered why this code compiles:
class X
{
int x;
int& y;
public:
X(int& _y):y(_y)
{
}
void f(int& newY) const
{
//x = 3; would not work, that's fine
y = newY; //does compile. Why?
}
};
int main(int argc, char **argv)
{
int i1=0, i2=0;
X myX(i1);
myX.f(i2);
...
}
As far as I understand, f() is changing the object myX, although it says to be const. How can I ensure my compiler complains when I do assign to y? (Visual C++ 2008)
Thank a lot!
Because you are not changing any variable in X. Actually, you are changing _y which is an outsider with respect to your class. Don't forget that:
y = newY;
Is assigning the value of newY to the variable pointed by y, but not the references them selves. Only on initialization the references are considered.
The situation is similar to pointer members. In a const member function, the const applies to the pointer itself, not the pointee.
It's the difference between:
X* const //this is how the const applies: you can modify the pointee
const X*
Except X& const isn't valid syntax, since the reference can't be made to refer to another object in the first place (they are implicitly always const). In conclusion: const on methods has no effect on member references.
As additional information for the accepted answer, I want to say, in fact one can
change variables in X.
Because you are not changing any variable in X.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Bar {
public:
void funcA() const {
c++;
}
int b = 3;
int &c = b;
};
int main()
{
Bar b;
b.funcA();
cout << b.b << endl; //4
}
So the main idea for this problem is:
It modifies what the member refers to, it does not modify the member.
This also applies for pointer members.
See here Why can reference members be modified by const member functions?
There is a rule about const methods. If the method is const, and we are trying to use another function at the same method, so it should be const as well. Otherwise, we will have a compilation error. I was trying to find the declaration of abs() function in math.h library, and here is what I found: Declarations of abs()
It means that the abs() function is not const, but when I use it inside const method I am not having a compilation error. can somebody explain why is that?
class D:public B,C
{
public:
D()
{
cout<<"This is constuctor D"<<endl;
}
int fun3() const;
~D()
{
cout<< "Destructor D"<<endl;
}
};
int D::fun3() const
{
int x=-3;
return abs(x);
}
To start, unlearn what you think you know. Let's look at what it means to be a const member.
class D {
public:
int fun2();
int fun3() const;
};
What does this declare? There is a class called D. There are two member functions fun2 and fun3, each taking a hidden this parameter and no other parameters.
Hold on! A hidden parameter? Well, yes. You can use this within the function; its value has to come from somewhere. All non-static member functions have this hidden parameter. However, not all non-static member functions have the same type of hidden parameter. If I were to show the hidden parameter, the declarations would look like the following:
int D::fun2(D * this);
int D::fun3(const D * this);
Notice how the const exists inside this pseudo-declaration? That is the effect of declaring a const member function: this points to a const object rather than a non-const object.
Now back to the question. Can fun3 call fun2? Well, fun3 would pass its this pointer (a pointer-to-const-object) to fun2, which expects a pointer-to-object. That would mean losing constness, so it's not allowed.
Can fun3 call abs? Well, fun3 would pass an integer to abs. No problem here. The problem is losing the constness of this. As long as you avoid that, you're fine.
There is a misunderstanding here about the constraint of const member functions.
A const member function can call whatever function it wants, as long as it doesn't change the state of the object. So fun3() compiles perfectly well, since it doesn't change any member variable and it doesn't call any non-const member functions for the same object.
Important note: public B,C might not be what you think: it means that D inherits publicly from B and privately from C. If you want it to inherit publicly from C you must state public B, public C.
const being applied to a method just means that the this pointer, i.e. the pointer to the instance on which the method is operating, is const. This implies that it cannot modify the fields and can only call const methods on it, not in general.
Calling a free function is perfectly acceptable, or even calling a non-const method on a different object of the same class, as long as such object is not const.
Consider this
#include <iostream>
int f(int num) { return num+1; }
int fr(int& num) { return num+1; }
int fcr(const int& num) { return num+1; }
class D
{
public:
int value= 0;
public:
void f1() { value++; }
int f2() const { return value; }
int f3() { return value; }
static void f4() { std::cout << "Hello" << std::endl; }
void f5() const;
};
void D::f5() const
{
// Prohibited:
// f1(); // modifies this
// f3(); // might modify this
// value++; // modifies this->value, thus modifies this
// value= 2; // modifies this->value, thus modifies this
// value= abs(value); // modifies this->value, thus modifies this
// fr(value); // takes value by reference and might modify it
//
// Permitted:
f2(); // const function, does not modify this
std::cout << value << std::endl; // independent function, does not modify this; read access to this->value is const
std::cout << abs(value) << std::endl; // independent function, does not modify this; read access to this->value is const
f4(); // static function, does not modify this
f(value); // function, does not modify this; takes value as read only (makes copy)
fcr(value); // function, does not modify this; takes value as read only by reference
D otherObject;
otherObject.f1(); // modifies otherObject (non const), does not modify this
}
int main()
{
const D d;
d.f5();
}
Whenever you call a member function like f4() inside f5() you're passing an implicit this pointer equivalent to this->f4(). Inside f5(), as it is const, this is not of type D* but rather const D*. So you can't do value++ (equivalent to this->value++ for a const D*. But you can call abs, printf or whatever that does not take this and tries to modify it).
When you take this->value if this type is D* it's type is int and you're free to modify it. If you do the same with a const D*, its type becomes const int, you cannot modify it, but can copy it and access it as a const reference for reading.
For a project I'm trying to create a vector class with vector function. I'm trying to add a vector addition function by overriding the += addition assignment. Because I don't want the += function to change the value to add I want to pass that value as a const reference.
My code:
Vector2D.h
#pragma once
class Vector2D
{
private:
int m_x, m_y;
public:
Vector2D(int x, int y);
int getX();
int getY();
void setX(int x);
void setY(int y);
Vector2D& operator+=(const Vector2D&);
};
Vector2D.cpp
#include "Vector2D.h"
Vector2D::Vector2D(int x, int y)
{
m_x = x;
m_y = y;
}
int Vector2D::getX()
{
return m_x;
}
int Vector2D::getY()
{
return m_y;
}
void Vector2D::setX(int x)
{
m_x = x;
}
void Vector2D::setY(int y)
{
m_y = y;
}
Vector2D& Vector2D::operator+=(const Vector2D& toAdd)
{
m_x += toAdd.getX();
m_y += toAdd.getY();
return *this;
}
But I get the errors:
the object has type qualifiers that are not compatible with the member
function "Vector2D::getX"
and
int Vector2D::getX(void)': cannot convert 'this' pointer from 'const
Vector2D' to 'Vector2D &'
I tried chaining the functions that return x and y to const:
const int Vector2D::getX()
const int Vector2D::getY()
but this won't solve the error. Remove the const from the parameter solves all errors and results in working code.
How should I change my code to make sure the value passed to the += operator can't be changed (for example by calling setY(100) on the object passed)?
Make Vector2D::getX() const as well. Otherwise you can't call it on an object you have by const reference.
Your attempt at adding const was applied to the functions return value, not the this pointer
const int Vector2D::getX()
Is a function on a non-const object that returns a const int.
int Vector2D::getX() const
Is a function on a const object.
This is one reason why it is often said that "a leading const is misleading".
getX() and getY() are non-const member functions, which can't be called with const object. Since they won't modify any members of class Vector2D, you should mark them as const member function, like
int Vector2D::getX() const
Note the position of const, which should be put at the end of the function declaration, means the function won't modify any members (except for mutable ones) of the class. const int Vector2D::getX() means the function will return a constant, it has nothing to do with the characteristic of the member function. In fact, return a constant build-in type doesn't make much sense, from the aspect of the caller side, it doesn't make any difference.
What you are looking for is : Constant Member Functions.
int Vector2D::getX() const
The const after the argument list in the function declarations indicates that the function does not modify the state of a object.
A const member function can be invoked for both const and non-const objects, whereas a non-const member function can be invoked only for non-const objects.
In your case, toAdd is const.
I have two questions about the following code.
class cls{
int vi;
public:
cls(int v=37) { vi=v; }
friend int& f(cls);
};
int& f(cls c) { return c.vi; }
int main(){
const cls d(15);
f(d)=8;
cout<<f(d);
return 0;
}
Why does it compile, since f(d) = 8 attemps to modify a const object?
Why does it still print 15, even after removing the const attribute?
It is not modifying a const object as a copy of d is being made due to the argument of f() being passed by value and not by reference. This is also the reason that d is unchanged as it is not being modified.
This question already has answers here:
Meaning of 'const' last in a function declaration of a class?
(12 answers)
Closed 7 years ago.
In C++ sometimes I see declarations like below:
return_type function_name( datatype parameter1, datatype parameter2 ) const
{ /*................*/}
What does this const type qualifier exact do in this case?
The const qualifier at the end of a member function declaration indicates that the function can be called on objects which are themselves const. const member functions promise not to change the state of any non-mutable data members.
const member functions can also, of course, be called on non-const objects (and still make the same promise).
Member functions can be overloaded on const-ness as well. For example:
class A {
public:
A(int val) : mValue(val) {}
int value() const { return mValue; }
void value(int newVal) { mValue = newVal; }
private:
int mValue;
};
A obj1(1);
const A obj2(2);
obj1.value(3); // okay
obj2.value(3); // Forbidden--can't call non-const function on const object
obj1.value(obj2.value()); // Calls non-const on obj1 after calling const on obj2
$9.3.1/3 states-
"A nonstatic member function may be declared const, volatile, or const volatile. These cvqualifiers affect the type of the this pointer (9.3.2). They also affect the function type (8.3.5) of the member function; a member function declared const is a const member function, a member function declared volatile is a volatile member function and a member function declared const volatile is a const volatile member function."
So here is the summary:
a) A const qualifier can be used only for class non static member functions
b) cv qualification for function participate in overloading
struct X{
int x;
void f() const{
cout << typeid(this).name();
// this->x = 2; // error
}
void f(){
cout << typeid(this).name();
this->x = 2; // ok
}
};
int main(){
X x;
x.f(); // Calls non const version as const qualification is required
// to match parameter to argument for the const version
X const xc;
xc.f(); // Calls const version as this is an exact match (identity
// conversion)
}
It means that it doesn't modify the object, so you can call that method with a const object.
i.e.
class MyClass {
public:
int ConvertToInteger() const;
};
Means that if you have
const MyClass myClass;
you can call
int cValue = myClass.ConvertToInteger();
without a compile error, because the method declaration indicates it doesn't change the object's data.