Интересно, есть ли способ объяснить компилятору, что: const A не изменит объект B, на который он ссылается. Таким образом, объект const A может быть создан с использованием объекта const B.
То, что вы хотите, это 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();
}
РЕДАКТИРОВАТЬ: (По запросу от @ бывшие известныеas_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 B
для передачи его на A
будет вызывать UB при вызове g2
, но это верно для всех B* ptr
с неизвестным происхождением, и класс A
ничего не может с этим поделать это.