C++ 将指向派生类的指针强制转换为指向基类的指针的引用
为什么我不能将指向派生类的指针强制转换为指向基类的指针的引用C++ 将指向派生类的指针强制转换为指向基类的指针的引用,c++,pointers,casting,reference,C++,Pointers,Casting,Reference,为什么我不能将指向派生类的指针强制转换为指向基类的指针的引用 struct Base { }; struct Derived : Base { }; int main() { Derived* derived = nullptr; static_cast<Base*&>(derived); } 只为你的错误 改变这个 static_cast<Base*&>(derived); to static_cast<Base*&g
struct Base { };
struct Derived : Base { };
int main()
{
Derived* derived = nullptr;
static_cast<Base*&>(derived);
}
只为你的错误
改变这个
static_cast<Base*&>(derived);
to
static_cast<Base*>(derived);
^^
static\u cast(派生);
到
静态_-cast(派生);
^^
如果您需要参考,请参见此处
Base* ptr = static_cast<Base*>(derived);
Base &ref = *ptr;
Base*ptr=static_cast(派生);
基准和参考=*ptr;
您不能将指针投射到引用-它们是完全不同的东西,因为
派生*
对象不是基*
对象,这两个对象完全可能具有不同的内存布局或值表示(例如,如果基
和派生
的对齐要求不同)。由于一个不是另一个,static\u cast
无法执行转换
如果您知道自己在做什么,并且知道类型双关没有问题,请使用类型双关的工具-重新解释\u cast
:
reinterpret_cast<Base*&>(derived);
reinterpret\u cast(派生);
并意识到误用的任何后果(与重新解释cast一样)。请特别注意,根据C++11 3.10/10,就标准而言,通过强制转换结果进行的任何访问都将是未定义的行为(尽管编译器可能会提供更强的保证)
请注意,在一般情况下,从Derived*
到Base*
的转换不一定是禁止操作的。例如,如果涉及多重继承,则可能涉及地址移动。如您的评论所示:
“不,这不是一个学术问题。我需要调用一个函数作为参数
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);
}
struct Base{};
派生结构:基{};
int main()
{
派生*派生=空PTR;
Base*Base=静态_转换(派生);
my_函数(base);//采用base*&参数
//如果需要指针值,请确保
//它是派生的*类型:
派生=静态_铸造(基础);
}
请注意,如果您在问题本身中包含了相关信息(来自我上面引用的评论),您可能会更快收到此答案。首先,
static\u cast
没有任何效果,因为您没有将返回值存储在任何位置。第二,如果您想将派生*
变量强制转换为基*
变量,那么就去掉&
。因此它应该类似于基*Base=static\u强制转换(派生)代码>。然而,有了当前的代码,您似乎可以简单地执行Base*Base=nullptr代码>,因为强制转换派生*
变量不会改变其值。这是一个学术问题,还是您确实需要此强制转换?不,这不是一个学术问题。我需要调用一个函数作为参数Base*&
。类型双关是将一种类型视为另一种类型的过程。像您提到的类型转换实际上并不涉及类型双关本身,因为对象没有取消引用。(换句话说,reinterpret\u cast
允许类型双关,但使用reinterpret\u cast
本身并不构成类型双关)。@davmac好吧,我有点假设OP实际上是在对类型双关的结果做一些事情,这很可能是类型双关。当然,从目前的情况来看,这只是一个禁止操作。在op给出的示例中(按照您的建议将static_cast更改为reinterpert_cast之后),对转换结果执行任何操作都会破坏别名规则,导致未定义的行为Base*
和Derived*
是不兼容的访问类型(3.10草案第15段)。3.10/15在已发布的C++11中根本不存在。C++11的最终草案是,你能在那里找到相关的参考资料吗?我得到的是5.2.10/7,11,这使得结果未指定。正如我在回答中所说:“如果你知道你在做什么,并且知道类型pun是可以的……”这是你的编译器文档可以告诉你的,例如。@Agnew在你链接的草稿中,它是3.10第10段(这通常被称为严格的别名规则,我可以向你保证它以某种形式出现在标准的任何最新版本中).但是在您的解决方案中,base
被my_函数
修改,而派生的
不变。@RuggeroTurra没错。采用Base*&
参数的函数不能保证将引用对象设置为派生*
值。如果确定指针将是派生的*
,则可以在函数完成后强制转换并分配它。我会更新答案。“你不能将指针投射到引用”-不正确;您可以将“指向T的指针”强制转换为“指向T的指针的引用”。结果是对原始指针的引用。
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);
}