reinterpret_cast указателя на указатель - PullRequest
0 голосов
/ 01 мая 2019

Если у меня есть указатель производного класса на указатель Derived** и я хочу преобразовать его в указатель базового класса на указатель Base**, использование static_cast<Base**>(ppd) не компилируется, и я вынужден использовать reinterpret_cast<Base**>, который, кажется, работает нормально. Для этого есть причина? Есть ли какие-то предостережения, о которых следует помнить при выполнении такого рода reinterpret_cast?

Ниже приведен пример кода, который я написал:

struct Base {
    Base(int x0) : x(x0) {}
    int x;
};

struct Derived : Base {
    Derived(int x0, int y0): Base(x0), y(y0) {}
    int y;
};

void foo(Base** ppb) {
    *ppb = new Derived(5, 7);
}

void bar(Derived** ppd) {
    foo(reinterpret_cast<Base**>(ppd));
}

int main() {
    Base* pb = new Base(3);
    cout << pb->x << endl;
    delete pb;

    foo(&pb);
    cout << pb->x << ' ' << static_cast<Derived*>(pb)->y << endl;
    delete pb;

    Derived* pd = new Derived(2,4);
    cout << pd->x << ' ' << pd->y << endl;
    delete pd;

    bar(&pd);
    cout << pd->x << ' ' << pd->y << endl;
    delete pd;
}

Ответы [ 2 ]

1 голос
/ 01 мая 2019

Тебе вообще не нужен reinterpret_cast:

void bar(Derived** ppd) {
    Base *base;
    foo(&base);
    *ppd = static_cast<Derived*>(base);
}
1 голос
/ 01 мая 2019

reinterpret_cast<Base**>(ppDerived) четко определено.Разыменование результата, если он указывает на указатель на производное, является неопределенным поведением, а не тем, что вам разрешено делать.«Кажется, что он работает нормально» - это один из возможных симптомов UB.

Что вам, вероятно, нужно:

Base* foo() {
  return new Derived(5, 7);
}

Derived* bar() {
  return static_cast<Derived*>(foo());
}

Это не содержит UB и логически эквивалентно.

Или вы можете сделать:

template<class...Ts>
using sink=std::function<void(Ts...)>;

void foo(sink<Base*> ppb) {
  ppb(new Derived(5, 7));
}

void bar(sink<Derived*> ppd) {
  foo([&](Base*b){ ppd(static_cast<Derived*>(b)); });
}

или даже

void foo(Base** ppb) {
  *ppb = new Derived(5, 7);
}

void bar(Derived** ppd) {
  Base*p=0;
  foo(&p);
  *ppd=static_cast<Derived*>(p);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...