Reputation: 681
Here is the code that i have
class A
{
public:
void Func1() const;
};
class B
{
public:
A* a;
void Func2() const
{
// do something with 'a'
}
};
void A::Func1() const
{
B b;
b.a = this;
b.Func2();
}
Now obviously this is giving me an error in the line, because I'm trying to convert from const to non-const.
b.a = this;
Is there any way to call Func2
without having to cast away the constness of this
. Since Func2
is a const function anyways, it will not change this
.
Upvotes: 2
Views: 552
Reputation: 437336
If class B
is always going to work with *a
as a const
object then as others have said all it takes is to simply change the declaration to
public: const A* a
At this point I should mention that the constness of B::Func2
is a red herring because it has absolutely no relation to the constness of B::a
. That B::Func2
is const
means that it's not allowed to change the value of a
; however, it is allowed to dereference a
and mutate the resulting object.
Now, if class B
has both const
and non-const
operations with respect to *a
then your class design needs to change. It would be much better if you switched class B
to use a const A* a
as above, and added another class D : public B
that encapsulates all the mutating operations. In addition, a
should be hidden behind a property setter; this allows you to do things like
class B {
const A* a;
public:
void setA(const A* a) { this->a = a; }
void Func2() const {}
};
class D : public B {
A* a;
public:
using B::setA;
void setA(A* a) {
this->a = a;
static_cast<B*>(this)->setA(const_cast<const A*>(a));
}
void Func3() { /* do something to D::a */ }
};
With this scheme both B
and D
keep independent, suitably typed pointers to the object to be accessed. If setA
is called on a B
, or on a D
with a const A*
parameter then only B::a
is set. If setA
is called on a D
with an A*
, then both B::a
and D::a
are properly set. This has become possible because by abstracting the member behind a setter you can then overload the setter on the constness of its parameter.
Upvotes: 1
Reputation: 55543
Yes, make the A *
constant:
class B {
public:
const A *a
...
};
Upvotes: 1
Reputation: 258568
Func2
may not change this
, but b.a
is not const
and you're free to change it afterwards. There's no right way to do this, although workarounds exist, such as mutable
or const_cast
.
It's the sign of a faulty design.
Upvotes: 1
Reputation: 21900
You have to declare the A*
as const:
class A
{
public:
void Func1() const;
};
class B
{
public:
const A* a;
void Func2() const
{
// do something with 'a'
}
};
void A::Func1() const
{
B b;
b.a = this;
b.Func2();
}
Since in A::Func1
, the this
pointer is const.
Upvotes: 3