Convert const T* const to T* - c++

is it possibile do this kind of cast in C++?
I need to declare my attribute in this way.
Class A {
public:
void update() { ++i_; }
private:
int i_;
}
Class B{
public:
void foo() {
a_->update(); /* Error */
}
private:
const A* const a_;
}
Error is:
passing ‘const A’ as ‘this’ argument of ‘void A::update()’ discards
qualifiers [-fpermissive]
I try with static_cast, but is not enough.. does not work.. any ideas?

You have two choices here. Either make A::update a const function-
Class A {
void update() const;
}
or remove the constness of the pointer.
Class B{
public:
void foo() {
const_cast<A*>(a_)->update();
}
private:
const A* const a_;
}
The former would be the preferred method, but that will also stop you from doing anything useful in class A's update.
As a rule of thumb, if you have to cast the const off something then you really want to look at why the pointer is const in the first place.

Using a const member with a non-const method is forbiden (unless using mutable). Put a const after declaration of foo() and update():
void update() const { ... }
^^^^^
void foo() const { ... }
^^^^^
or ...
If you don't want to make update a const, you can use const_cast:
void foo() const // Now, this const keyword is optional but recommanded
{
const_cast<A*>(a_)->update();
^^^^^^^^^^^^^^
}

You've got a few options:
use const_cast to cast away the const and call the method.
make update a const method, so that it can be called through a const pointer.
don't store a_ as const in the first place. Change it to A* const a_ so that you can call non-const methods, but the pointer cannot be changed.

Assuming that you cannot declare the method as const and that you know what you are doing (tm) and why this is bad: Try the const_cast!

The const after * has nothing to do with it. You must declare your functions which use a_ as const functions. If they don't compile, you must use const_cast or reinterpret_cast to remove const from the pointer before calling.. But this is very dodgy, and if update() function modifies an object which was originally declared const, this is undefined behaviour.

The error you get
passing ‘const A’ as ‘this’ argument of ‘void A::update()’ discards
qualifiers [-fpermissive]
is result of calling non-const method on a const pointer. This is forbidden. Since you require an update to be non-const and you cannot store a pointer to non_const A, you can use operator const_cast to cast away const and here is how to do it:
class A {
public:
void update(){}
};
class B{
public:
void foo() {
const_cast< A*>(a_)->update(); /* OK*/
}
private:
const A* const a_;
};
You should however rethink your design.

As mentioned by someone before, use mutable/const but this changes your design a little bit:
class A {
public:
void update() const { ++i_; } // this will make the method callable by const A*
private:
mutable int i_; // and this will make you field mutable in a const method
};
class B{
public:
void foo() {
a_->update();
}
private:
const A* const a_;
};

Related

I have Question about class overriding in C++

When I study about override keyword, I found some strange thing like below code.
#include <iostream>
template <class T>
class A
{
public:
virtual void some_function(const T a)
{
std::cout<<__PRETTY_FUNCTION__<<std::endl;
std::cout<<"Base"<<std::endl;
}
};
class Derived : public A<int*>
{
public:
virtual void some_function(const int* a)
{
std::cout<<__PRETTY_FUNCTION__<<std::endl;
std::cout<<"Derived"<<std::endl;
}
};
int main()
{
A<int*>* p = new Derived;
p->some_function(nullptr);
delete p;
}
When I first saw that code, I expected "Derived" to be called.
But above code print result like below.
void A<T>::some_function(T) [with T = int*]
Base
But when I removed const keyword in the some_function that placed in Derived class,
class Derived : public A<int*>
{
public:
virtual void some_function(int* a)
{
std::cout<<__PRETTY_FUNCTION__<<std::endl;
std::cout<<"Derived"<<std::endl;
}
};
It print "Derived".
Can you tell me why this is happening?
The function prototypes are not the same. For T=int* const T a: a is a const pointer to an int, while const int *a is a pointer to an const int. For one the pointer is const, for the other the int is const.
int * const a would be the same as const T a, or you can make T=const int*.
https://godbolt.org/z/WEaEoGh58
Also important to note: When you derive from a class you must declare a virtual destructor.
A hint: when you use the keyword override on the derived function, you will get an error that you are not overriding the function: https://godbolt.org/z/o87GMrhsd
At
const T a
const qualifier is interpreted as top-level cv-qualifier for T, so it is processed
T const a
thus if int* is set to T, parameter type becomes
int* const a
So, your Derived's function signature (it is called second level const qualifier)
const int* a
is different from Base's one. As a result, your Derived virtual function is not called.
In addition, C++ has the rule of "ignore top-level cv-qualifier from function signature". So, your Base's signature
int* const
and if you give the type of
int*
into Derived's signature, these two types signature are interpreted to be equivalent. As a result, your Derived virtual function is called correctly.
The following is a back-ground for your help. The type of
T*
has two component T and pointer and then
T* const
is called top-level cv-qualifier which is applied to *, and then
T const *
is called second level cv-qualifier which is applied to T (equal to const T*). C++ ignore top-level cv-qualifier from signature. On the other hand, second level qualifier is included to signature. Therefore for example,
void f(int*) {}
void f(int* const){}
is failed to compile because of same signature by top-level cv-qualifier ignoring. In contrast,
void f(int*) {}
void f(int const * ){}
is compiled successfully by the difference of second level cv-qualifiers.
This is important to understand the behavior of virtual function calls. The reason is that the signature of derived virtual function and base's one must be identical to call it correctly.

const correctness and member pointers

I have const on the Accelerate method, yet I can call the power method. Is their a way to actually stop this.
class Engine{
public:
void Power(){
}
};
class Car{
public:
Car() : p(new Engine()){}
void Accelerator() const{
p->Power();
}
private:
Engine* p;
};
For Car, a const method is a methods which does not modify Car member variables.
so, as long that Car::Accelerator does not make p point to a different location, it is valid.
since p is not modified in Accelerator (meaning it does not point to a different memory address), the program is valid.
the moment you make p point to a different location, the program fails to compile:
void Accelerator() const {
p= nullptr; //wrong
}
Const protection affects only the direct members, in this case the pointer only. Values outside this object (aka. pointed values) are not protected.
You have to decide if you consider the pointed value as yourself or someone else.
You can modify the member Engine as const*, which will make the Engine object pointed to by p in Car const:
class Engine{
public:
void Power(){
}
};
class Car{
public:
Car() : p(new Engine()){}
void Accelerator() const{
p->Power();
}
private:
Engine const* p;
};
This will no longer compile:
test_const.cpp:12:9: error: member function 'Power' not viable: 'this' argument
has type 'const Engine', but function is not marked const
p->Power();
^
test_const.cpp:3:10: note: 'Power' declared here
void Power(){
^
But this implies that no member of Car can modify *p, which is probably not what you intend. See #NathanOliver's comment for better answer.
Hope this helps.

Cannot call a method of const reference parameter in C++

class A
{
public:
A(){};
~A(){};
void method(){};
};
void call(const A &a)
{
a.method(); // I cannot call this method here if I use "const" but I can call it if not using "const"
}
int main()
{
A a;
call(a);
return 0;
}
In this case, the error is: "passing const A as this argument of void A::method() discards qualifiers [-fpermissive]|"
In function call, if I use const, I get the error, but if I get rid of it, it works.
Can anyone explain it for me?
You can't call non-const member functions via const references. You can fix this by making the member function const:
void method() const {};
^^^^^
This indicates that calling the member does not mutate the object it is called on*
* Conceptually. In practice it can mutate members marked mutable

C++ const method on non const pointer member

I was wondering how protect a non const pointer member from an object throught a const method. For example:
class B{
public:
B(){
this->val=0;
}
void setVal(){
this->val = 2;
}
private:
int val;
};
class A{
public:
A():b(new B){}
void changeMemberFromConstMethod() const{
this->b->setVal();
}
private:
B * b; // how to protect data pointed in A::changeMemberFromConstMethod
}
Is it possible to "protect" A::b data pointed from his method?
After many research on web, no satisfied reponse found yet.
Thanks for your help.
Something like this, perhaps:
template <typename T>
class deep_const_ptr {
T* p_;
public:
deep_const_ptr(T* p) : p_(p);
T* operator->() { return p_;}
const T* operator->() const { return p_;}
};
class A {
deep_const_ptr<B> b = new B;
};
deep_const_ptr behaves like a const T* const pointer in A's const methods, and like T* in non-const methods. Fleshing the class out further is left as an exercise for the reader.
If you change the member of A from
B* b;
to
B b;
then you will get the expected behavior.
class A{
public:
A() : b() {}
void changeMemberFromConstMethod() const{
this->b.setVal(); // This will produce a compiler error.
}
private:
B b;
}
The problem you have is that a const method makes all the member variables const. In this case however, it makes the pointer const. Specifically, it's as if all you have is B * const b, which means a constant pointer to a (still) mutable B. If you do not declare your member variable as const B * b, (that is, a mutable pointer to a constant B), then there is no way to protect from this behavior.
If all you need is a const B, then by all means, define A like this:
class A {
public:
A() : b(new B) {}
// This WILL give an error now.
void changeMemberFromConstMethod() const { b->setVal(); }
private:
const B* b;
}
However, if other methods of A mutate B, then all you can do is make sure that B does not get mutated in your const methods of A.
Try using the following general approach, to protect the const-ness of objects referenced via pointers, in this situation.
Rename B *b
B *my_pointer_to_b;
And change the initialization in the constructor accordingly.
Implement two stubs:
B *my_b() { return b; }
const B *my_b() const { return b; }
Replace all existing references to b with my_b(), in the existing code. Going forward, in any new code, always use my_b() to return the pointer to b.
Mutable methods will get a non-const pointer to B; const methods will get a const pointer to B, and the extra step of renaming makes sure that all existing code is forced to comply with the new regime.

Compiler Error with const function

I am not sure whether I am missing something basic. But I am unable to understand why the compiler is generating the error for this code:
class A
{
};
class B
{
public:
B();
A* get() const;
private:
A* m_p;
};
B::B()
{
m_p = new A;
}
A* B::get() const
{
//This is compiling fine
return m_p;
}
class C
{
public:
A* get() const;
private:
A m_a;
};
A* C::get() const
{
//Compiler generates an error for this. Why?
return &m_a;
}
EDIT: The compiler error is : error C2440: 'return' : cannot convert from 'const class A *' to 'class A *' Conversion loses qualifiers
const in the function signature tells the compiler that the object's members may not be modified. Yet you return a non-const pointer to a member, thus allowing a violation of that promise.
In your class B, you make/break no promise since you don't return a pointer to a member, you return a copy of it (and the member happens to be a pointer).
It's because you're returning a non-const pointer to a member from a const function.
The first part works because you're returning a copy of a member pointer, so this doesn't violate the const-ness of the get function:
class B
{
public:
B();
A* get() const;
private:
A* m_p;
};
A* B::get() const
{
//This is compiling fine
return m_p;
}
But the next bit generates the compile error (on gcc 4)
testfile.cpp:37: error: invalid conversion from ‘const A*’ to ‘A*’
Because your const get function is providing non-const acess to m_a by returning a non-const pointer to it.
class C
{
public:
A* get() const;
private:
A m_a;
};
A* C::get() const
{
//Compiler generates an error for this. Why?
return &m_a;
}
Because the returned pointer is not const. Change it to this:
class C
{
public:
const A* get() const;
private:
A m_a;
};
const A* C::get() const
{
//Compiler generates an error for this. Why?
return &m_a;
}
Notice that C::get() now returns a const pointer to A.
Member functions marked const cannot return a non-const reference or pointer to a private variable. If the compiler allowed this, anyone outside your class would be able to modify the said private variable and the const qualifier on the function would lose meaning.
This problem can be illustrated with a simpler example:
class MyClass {
public:
int *get() const;
private:
int value;
};
int *MyClass::get() const {
return &value;
}
In MyClass::get() const, value has the type const int. When you dereference it, you get const int *. That type cannot be safely (implicitly) casted to int *. To correct your problem, have get() return const int *.
A* C::get() const
{
//Compiler generates an error for this. Why?
return &m_a;
}
Because get() is a const function, the compiler treats all member variables it refers to as const. When you take the address of such a member, you get a pointer to const. But your function is returning a non-const pointer. You need to change your code to
const A* C::get() const
{
return &m_a;
}
Basically just add a const in front,
const A* C::get() const
{
//Compiler generates an error for this. Why?
return &m_a;
}
Then if you want to access it, basically do:
C something;
const A* a = something.get();
However, your program makes very little sense, to me.
IMO, it would make most sense to do:
class A{
};
class C : public A
{
};
That way you don't have to make a "get" that returns the instance of A.