将指向派生类的指针转换为引用指向基类的指针

问题描述 投票:0回答:5

为什么我无法将指向派生类的指针转换为引用指向基类的指针?

struct Base { };
struct Derived : Base { };

int main()
{
    Derived* derived = nullptr;
    static_cast<Base*&>(derived);
}    

我得到:

invalid static_cast from type 'Derived*' to type 'Base*&'
c++ pointers casting reference
5个回答
3
投票

根据您的评论:

“不,这不是一个学术问题。我需要调用一个以参数为参数的函数

Base*&

解决此问题的正确方法是创建一个适当类型的新指针变量,并将其(或者更确切地说,对其的引用)传递给相关函数:

struct Base { };
struct Derived : Base { };

int main()
{
    Derived* derived = nullptr;
    Base* base = static_cast<Base*>(derived);
    my_function(base); // takes a Base*& argument

    // If you need the pointer value and are sure that
    // it's a Derived* type:
    derived = static_cast<Derived*>(base);
}

请注意,如果您在问题本身中包含相关信息(来自我上面引用的评论),您可能会更快收到此答案。


2
投票

因为

Derived*
对象不是
Base*
对象,并且两者完全有可能具有不同的内存布局或值表示(例如,如果
Base
Derived
的对齐要求不同)。由于一个不是另一个,
static_cast
无法执行转换。

如果您知道自己在做什么并且知道类型双关语没问题,请使用类型双关语工具 —

reinterpret_cast
:

reinterpret_cast<Base*&>(derived);

并注意误用的任何后果(与往常一样

reinterpret_cast
)。特别注意,根据 C++11 3.10/10,就标准而言,通过转换结果进行的任何访问都将是未定义行为(尽管您的编译器可能会提供更强的保证)。

请注意,在一般情况下,从

Derived*
Base*
的转换不必是无操作。例如,如果涉及多重继承,则可能涉及地址移位。


0
投票

扩展https://stackoverflow.com/users/1782465/angew-is-no-longer-proud-of-so提供的答案,您可以尝试此代码来了解为什么引用 Base* (即

Base*&
) 无法绑定到
Derived*
:

struct B {
    int valb;
};

struct D : B {
    int vald;
};

template<typename T>
struct SC {
    T vald_sc;
};

template<typename T>
struct MV {
    int valmv;
    T& valb;
    MV(T& vb) : valb(vb) {}
};

void f1(B* dp) {
}

void f2(B*& dp) {
}

void f3(B** dp) {
}

int main() {
    SC<D> sc;
    MV<B> mv(sc.vald_sc); //Conversion succeeds because a D object is a B object: their memory layout starts at the same addr

    SC<D*> scp;
    //MV<B*> mvp(scp.vald_sc); //Error: candidate constructor not viable: no known conversion from 'D *' to 'B *&' for 1st argument
    //NB: A D* object is not a B* object.
    MV<B*> mvp1(reinterpret_cast<B*&>(scp.vald_sc));
    MV<B*> mvp2(*reinterpret_cast<B**>(scp.vald_sc));

    f1(scp.vald_sc);
    f2(reinterpret_cast<B*&>(scp.vald_sc));
    f2(*reinterpret_cast<B**>(scp.vald_sc));
    f3(reinterpret_cast<B**>(&scp.vald_sc));
    return 0;
}

-1
投票

仅针对您的错误 改变这个

static_cast<Base*&>(derived);
to 
static_cast<Base*>(derived);
                ^^

请参阅此处 http://ideone.com/1QuMLK


-1
投票

如果您想要参考,您需要做

Base* ptr = static_cast<Base*>(derived);
Base &ref = *ptr;

你不能将指针转换为引用 - 它们是完全不同的东西

© www.soinside.com 2019 - 2024. All rights reserved.