想象一下,我有一个对象A,该对象A通过其地址引用了对象B。 B的地址在A的构造函数中给出。 A的某些方法可以修改B,其他方法则不能。
这是一个非常简单的例子:
class B {
public :
void f1() const;
void f2();
};
class A {
public :
A(B * pb) {m_pb=pb;}
void g1() {m_pb->f1();} // g1 do not modify *m_pb
void g2() {m_pb->f2();} // g2 do modify *m_pb
private :
B * m_pb;
}
现在,假设在我的代码的某些部分中,我有一个类型为const B&的变量。我想创建一个对象A来调用不修改对象B的g1方法。但是我根本无法构造对象A。
一种解决方案是创建两个类A1和A2,其中A1引用const B *并仅定义方法g1,而A2引用B *并定义g1和g2。 (g1将在2个不同的位置定义)。我觉得这种解决方案不是很优雅。
我想知道是否有一种方法可以向编译器解释: const A不会修改它所引用的对象B。因此可以使用const B对象构造const A对象。
答案 0 :(得分:2)
我想知道是否有一种方法可以向编译器解释:const A不会修改它所引用的对象B.因此可以使用const B对象构造const A对象。
您想要的是const constructor,没有一个。但是您可以避免使用继承来复制接口:
struct B{
void f1() const{}
void f2() {}
};
class constA
{
public:
constA(const B* b):b(b){}
// Should be const as it does not changes `constA` object.
void g1() const {b->f1();}
// No harm in this, but can be protected if you want
const B* getB() const { return b;}
private:
const B* b;
};
class A : public constA
{
public:
A(B* b):constA(b){}
void g2() const { getMutableB()->f2();}
private:
B* getMutableB() const { return const_cast<B*>(getB());}
};
int main()
{
B b;
const B cb;
A a(&b);
a.g2();
a.g1();
constA ca(&cb);
ca.g1();
//ca.g2();
constA ca2(&b);
ca.g1();
//ca.g2();
}
编辑:(根据我同意的@ formerlyknownas_463035818的请求)在const_cast
上进行快速刷新:
int main()
{
const int x = 5;
int y = 5;
const int* c_ptr = &x;
//'ptr' is valid object with known value.
int* ptr = const_cast<int*>(c_ptr);
// Is valid because '*ptr' is not modified
int value = *ptr;
// Undefined behaviour because '*ptr' is const object.
*ptr = 5;
const int* c_ptr2 = &y;
//'ptr2' is valid object with known value.
int* ptr2 = const_cast<int*>(c_ptr2);
// Is valid because '*ptr2' is not modified
int value = *ptr2;
// Is valid because '*ptr2' is not a const object.
*ptr2 = 5;
}
鉴于A
仅具有非常量B
构造函数,则getB()
始终返回指向非const对象的指针。因此,上面示例的第二部分适用,一切都安全。
请注意,在调用const B
时,将const cast A
传递给g2
会产生UB,但这对于所有来历不明的B* ptr
都是如此, A
类对此无能为力。