C++ 重新解释指针到指针的转换

C++ 重新解释指针到指针的转换,c++,reinterpret-cast,C++,Reinterpret Cast,如果我有一个指向指针derived**的派生类指针,并希望将其转换为指向指针base**的基类指针,那么使用static\u cast(ppd)不会编译,并且我被迫使用reinterpret\u cast,这似乎工作得很好。这有什么原因吗?在进行这种重新解释时,我是否应该记住一些注意事项 下面是我编写的一段示例代码: struct Base { Base(int x0) : x(x0) {} int x; }; struct Derived : Base { Deriv

如果我有一个指向指针
derived**
的派生类指针,并希望将其转换为指向指针
base**
的基类指针,那么使用
static\u cast(ppd)
不会编译,并且我被迫使用
reinterpret\u 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;
}
struct Base{
基(int x0):x(x0){}
int x;
};
派生结构:基{
导出的(intx0,inty0):基(x0),y(y0){
int-y;
};
无效foo(基准**ppb){
*ppb=新衍生(5,7);
}
空心条(导出**ppd){
foo(重新解释演员阵容(ppd));
}
int main(){
基底*pb=新基底(3);
cout x
reinterpret_cast(ppDerived)
定义良好。如果结果是指向派生指针的指针,则取消引用该结果是未定义的行为,并且不允许您执行此操作。“它似乎工作正常”是UB的一个可能症状

您可能想要的是:

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

Derived* bar() {
  return static_cast<Derived*>(foo());
}
Base*foo(){
返回新导出的(5,7);
}
派生*bar(){
返回静态_cast(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)); });
}
模板
使用sink=std::函数;
无效foo(水槽ppb){
ppb(新衍生的(5,7));
}
空栏(水槽ppd){
foo([&](Base*b){ppd(static_cast(b));});
}
甚至

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

void bar(Derived** ppd) {
  Base*p=0;
  foo(&p);
  *ppd=static_cast<Derived*>(p);
}
void foo(基准**ppb){
*ppb=新衍生(5,7);
}
空心条(导出**ppd){
基准*p=0;
foo&p;
*ppd=静态铸件(p);
}
reinterpret_cast(ppDerived)
定义良好。如果结果是指向派生指针的指针,则取消引用该结果是未定义的行为,并且不允许您执行此操作。“它似乎工作正常”是UB的一个可能症状

您可能想要的是:

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

Derived* bar() {
  return static_cast<Derived*>(foo());
}
Base*foo(){
返回新导出的(5,7);
}
派生*bar(){
返回静态_cast(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)); });
}
模板
使用sink=std::函数;
无效foo(水槽ppb){
ppb(新衍生的(5,7));
}
空栏(水槽ppd){
foo([&](Base*b){ppd(static_cast(b));});
}
甚至

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

void bar(Derived** ppd) {
  Base*p=0;
  foo(&p);
  *ppd=static_cast<Derived*>(p);
}
void foo(基准**ppb){
*ppb=新衍生(5,7);
}
空心条(导出**ppd){
基准*p=0;
foo&p;
*ppd=静态铸件(p);
}

您实际上根本不需要重新解释演员阵容

void bar(Derived** ppd) {
    Base *base;
    foo(&base);
    *ppd = static_cast<Derived*>(base);
}
void条(派生**ppd){
基地*基地;
foo&base;
*ppd=静态铸件(底座);
}

您实际上根本不需要重新解释演员阵容:

void bar(Derived** ppd) {
    Base *base;
    foo(&base);
    *ppd = static_cast<Derived*>(base);
}
void条(派生**ppd){
基地*基地;
foo&base;
*ppd=静态铸件(底座);
}

我被迫使用reinterpret\u cast,您可能没有被迫这么做,所以请告诉我们是什么导致您得出这样的结论。我知道这是一种糟糕的编码风格,但这只是一个过于简单的示例,实际上它是一些我无法更改的遗留接口……还想知道这背后的原因是什么你的膝盖或者你能说服你周围的人不要强迫你使用reinterpret_cast?这听起来像是一种可怕的做法。如果修改
foo
以创建
(或任何不是从
派生的
派生的类)可能会重复这个大警告,
pd
在调用后将不再指向
派生的
。我被迫使用reinterpret\u cast,您可能不是被迫这样做的,所以请告诉我们是什么导致您得出这样的结论。我知道这是一种糟糕的编码风格,但这只是一个过于简化的示例,事实上,它是一些我无法更改的遗留接口…而且我想知道这背后的原因是什么?它是一个扔在你膝上的界面,还是你能说服你周围的人不要强迫你使用reinterpret_cast
?这听起来像是一个可怕的做法。如果修改
foo
来创建一个
Base
(或不是从
派生的任何类
),
pd
将不再在调用后指向
派生的