The member is non const, and the member's member function is non const, when it is called on a const member function, it will generate an error, complains about:
error: passing 'const foo' as 'this' argument discards qualifiers [-fpermissive]
code:
// this class is in library code i cannot modify it
class CWork {
public:
const string work(const string& args) { // non const
...
return "work";
}
};
// this is my code i can modify it
class CObject {
private:
CWork m_work; // not const
public:
const string get_work(const string& args) const { // const member function
return m_work.work(args); // error here
}
};
Why is this and how to fix this?
Compiler is g++ 5.3.1.
Inside a const method the object (*this) and hence all its members are const. Think about it, if this wasnt the case then an object being const would not mean anything.
Thus m_work is const inside get_work and you can only call const methods on it.
Make work also a const method. There is no apparent reason to make it not const and by default you should make methods const. Only when you need to modify the object make them non-const.
it's in library i cannot change it.
In that case you are out of luck. You can only make get_work non const too, because work seems to modify m_work hence modifies your CObject which you cannot do in a const method.
Related
I have an interesting predicament here where the code will compile if I pass a variable by value to the function but not if I pass it by reference, and I'm not sure why. In header.h:
#include <iostream>
#include <string>
void get_name(std::string &name)
{
getline(std::cin, name);
return;
}
template <class T, class U>
class readonly
{
friend U;
private:
T data;
T& operator=(const T& arg) {data = arg; return data;}
public:
operator const T&() const {return data;}
};
class myClass
{
private:
typedef readonly<std::string, myClass> RO_string;
public:
RO_string y;
void f()
{
get_name(y); // compile error
}
};
The main.cpp implementation file simply includes this header file, creates an instance of myClass and then calls f(). When doing so, it won't compile properly. The problem lies in the fact that I'm passing the variable y by reference to the get_name function. If I change the function so that I pass by value instead, everything compiles properly and works as expected (except I'm obviously not making changes to y anymore). However, I don't understand this behavior. Why does this happen and is there an optimal way to fix it in this situation?
Your conversion operator:
operator const T&() const {return data;}
Only allows implicit conversion to a const reference. This makes sense since you are interested in making something read only. But get_name requires a non-const reference to a string. That is, get_name expects to be able to mutate its input. The type being passed in cannot convert to a mutable string reference, only to a constant string reference, so it doesn't compile.
When you pass by value, it simply constructs a new string from the const reference to pass into the function, which is fine.
Intuitively, a function called get_name should probably take a const reference since it shouldn't need to mutate its input just to get the name.
As explained by Nir Friedman, get_name(y); invoques the implicit conversion operator which gives you a const reference.
But, as you wrote friend U;, myClass has access to the private member data of y and allows you to do:
get_name(y.data);
I don't understand why this piece of code won't compile.
I get following error in line return source->GetA();
cannot convert 'this' pointer from 'const class FooStruct' to 'class
FooStruct &'
If I remove the const keyword it compiles fine.
class FooStruct
{
int a;
public:
int GetA() {return a;};
int Bar(const FooStruct *source);
};
int FooStruct::Bar(const FooStruct *source)
{
return source->GetA();
}
The code itself doesn't make sense. It has been stripped down from some real code and its only purpose is to illustrate the problem.
It is because of this line:
return source->GetA();
Here you are trying to execute GetA function on the pointer that you got. If the pointed object is const, the function must also be const, because:
Both const and non-const functions can be executed on non-const objects
Only const functions can be executed on const objects.
It is a good idea to mark all the functions that do not modify the state of the object as const, so they can be used on const objects (e.g. in functions that accept const T & as a parameter).
So in your case, the class should look like:
class FooStruct
{
public:
int GetA() const {return a;}
};
The function GetA itself needs to be marked const:
int GetA() const {
return a;
}
This then allows a const source* pointer to call that function.
I have a class like this:
class MyClass
{
const int GetValue()
{
return 2;
}
}
and I am passing it to a function like this:
void Test(const MyClass &myClass)
{
int x=myClass.GetValue();
}
But I am getting this error:
The object has type qualifiers that are not compatible with member function Object type is const MyClass
I know that if I define function like this:
void Test( MyClass &myClass)
But I want to know why adding const should generate such error?
You need to make the member function const, not the return type:
int GetValue() const;
This makes it possible to call this member on a const instance (or via a const reference or pointer).
Note: as you are returning by value, the constness of the thing you return is decoupled from the constness of the object returning it. In fact, it is very unlikely that you want the return type to be const.
You set the int to const, try making the method const like so:
const int GetValue() const
{
return 2;
}
There are two problems, a visibility problem (your const int GetValue() function is not visible since private) and the fact that you're calling a non-const function (which can perform modifications to the object which has it as a member function)
const int GetValue()
from a constant reference to the class
const MyClass &myClass
you are basically asking for "This object shall not be modified, anyway let me call a function which does not guarantee this".
You're not being coherent.
Given the following code:
#include <iostream>
#include <string>
using namespace std;
class A
{
private:
string m_name;
string m_first;
public:
A(): m_first("string") {}
virtual void print() const {}
string& getName() const {return m_first;} // won't compile
const string& getLastName() const {return m_name;} // compile
};
int main()
{
A a;
return 0;
}
Compiler presents : "invalid initialization of reference of type 'std::string&' from expression of type 'const std::string'"
Why can't I return "m_first" from getName() ? I thought that the const on the tail of the function states that the function will not change 'this'... but I'm not trying to change this , just return a data member.
Because inside a const method, all non-mutable members are implicitly const. So, you're trying to bind a reference to non-const std::string (your return value) to an object of type const std::string, which is illegal(because it would allow modification of const data), hence the error.
By returning a reference, you are saying you can modify the class data-member that the reference-variable is implicitly pointing to, and therefore modify the class ... but you have dedicated the class method as a constant method, meaning it is not allowed to change any class member variables that have not been specifically declared mutable. So by returning a non-constant reference, you are breaking the encapsulation "contract" that the class interface has established. Your options are to either return a temporary object (i.e., that creates a copy of the object), or a constant-reference. So you could either do
const string& getName() const {return m_first;}
or
string getName() const { return m_first; } //copies m_first and returns the copy
Your code promises that the reference won't change the m_name member, but you return a reference that can change it. What you want is a string const& return type.
This returns a "read-only" reference to m_name.
See also: the C++ FAQ on const correctness
When you return string &, it allows modifying class member... but the function is const, so it is not allowed to allow such a situation. But when you return const string &, it doesn't allow modifying class instance.
What if you call A.getName().ModifyTheString() ==> this means you modified this.
I'm confused about constant objects in C++
When we have passed a constant object/ reference of a const object is that mean that we cannot edit the attribute values of that object ?
or if its not whats the mean or constant in that is it 'refer' object' or 'attributes'
also when we return a constant object
declaring the function like
return_type function_name(parameters) const
{
}
the const keyword is at end of the function is it syntax ? and why if we return a const object shouldn't it be like follows
const return_type function_name(parameters)
{
}
Sorry if its a noob question ;)
This syntax:
return_type function_name(parameters) const
{
}
Indicates that function_name() may be invoked for an instance of the class that is const. It doesn't have any effect on the const-ness of the return value.
const return_type function_name(parameters)
{
}
...indicates that the value being returned from function_name() is const (and says nothing about the const-ness of the object having its member function called.)
When we have passed a constant object/ reference of a const object is that mean that we cannot edit the attribute values of that object ?
Yes. If the function is const, then the function cannot modify any non-mutable fields on the class. (Or call any other non-const method on the class).
and why if we return a const object shouldn't it be like follows
Because the return type can be constant too. Consider the following:
#include <string>
class MyClass
{
std::string data;
public:
void SetData(const std::string& content)
{
data.assign(content);
}
const std::string& GetData() const //Note that the function is const, and so
{ //is the reference it returns.
return data;
}
};
Note that we are returning a const reference to the internal member. If we returned a non const reference, than someone would be able to use the reference to modify the private member of the class, in this case MyClass::data.
Effectively the added const changes the first "hidden" parameter of the method from ClassType * const this to const ClassType * const this.