Ако 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
са правилно зададени. Това стана възможно, защото чрез абстрахиране на члена зад сетер можете да претоварите сетера относно постоянството на неговия параметър.
person
Jon
schedule
17.05.2012