Указатель на базовый класс
-
27-09-2019 - |
Вопрос
Если у меня есть следующие классы:
class A
{
...
}
class B
{
...
}
class C : public A, public B
{
...
}
и где-то я обнаруживаю, что указатель класса B
что у меня на самом деле указывает на класс C
, но функция требует указателя на класс A
, Что я могу сделать, чтобы получить этот указатель на класс A
?
Решение
Если вы точно знаете, что у вас есть B*
это указывает на C
объект, вы можете использовать пару static_cast
S:
B* bp = new C();
C* cp = static_cast<C*>(bp);
A* ap = static_cast<A*>(cp);
Единственный способ отказаться от иерархии наследования - использовать dynamic_cast
, который требует, чтобы тип полиморфной (то есть ваш класс должен иметь по меньшей мере одну функцию виртуального элемента; Поскольку ваши деструкторы базового класса должны быть virtual
, Это обычно не проблема):
B* bp = new C();
A* ap = dynamic_cast<A*>(bp);
dynamic_cast
Дополнительное преимущество в том, что если он не удается (то есть, если bp
на самом деле не указывает на C
), он возвращает NULL. Он имеет недостаток небольшой стоимости производительности (static_cast
эффективно свободен во время выполнения).
Другие советы
Код
class A
{
};
class B
{
};
class C : public A, public B
{
};
int main() {
C c;
A *a = &c;
}
Действительно, так как C уже A, поэтому назначение действитеется.
Если C наследует от A, как вы показали, то указатель C * должен быть неявно конвертирован в указатель A *. Возможно ли, что вы не включали декларацию класса C, чтобы компилятор не знал об этом наследственным отношениям? Или что на самом деле есть разные отношения наследства, чем данные в вашем вопросе? Какой-то код будет полезен для диагностики этой проблемы.
Редактировать
На основании обновленной версии вашего вопроса:
// Converts b to type A*, but only if it is actually
// of type C; otherwise, returns NULL
A* convertBtoAviaC(B* b) {
C* c = dynamic_cast<C*>(b);
return c; // note may be NULL, if b is not a C
}