这是我的代码
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();
}
现在显然这会给我一个错误,因为我正在尝试从const转换为非const。
b.a = this;
有没有办法调用Func2
而不必抛弃this
的常量。由于Func2
无论如何都是const函数,因此不会更改this
。
答案 0 :(得分:3)
您必须将A*
声明为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();
}
因为在A::Func1
中,this
指针是常量。
答案 1 :(得分:1)
Func2
可能不会更改this
,但b.a
不会const
,您可以随后更改它。尽管存在变通办法,例如mutable
或const_cast
,但没有正确的方法可以执行此操作。
这是设计错误的标志。
答案 2 :(得分:1)
是的,让A *
保持不变:
class B {
public:
const A *a
...
};
答案 3 :(得分:1)
如果class B
总是与*a
作为const
对象一起使用,那么正如其他人所说的那样,只需将声明更改为
public: const A* a
此时我应该提到B::Func2
的常量是一个红色的鲱鱼,因为它与B::a
的常量完全没有关系。 B::Func2
为const
意味着不允许更改a
的值;但是, 允许取消引用a
并改变生成的对象。
现在,如果class B
对const
进行const
和非*a
操作,则您的班级设计需要更改。如果您将class B
切换为如上所述使用const A* a
并添加另一个class D : public B
来封装所有变异操作,那会更好。此外,a
应隐藏在属性设置器后面;这允许你做像
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 */ }
};
使用此方案,B
和D
都保持独立的,适当类型的指向要访问的对象的指针。如果在setA
或B
上使用D
参数调用const A*
,则仅设置B::a
。如果在setA
上使用D
调用A*
,则B::a
和D::a
都会正确设置。这已成为可能,因为通过抽象setter后面的成员,您可以在其参数的constness上重载setter。