首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >静态强制转换允许转换对象指针,但不允许整数。

静态强制转换允许转换对象指针,但不允许整数。
EN

Stack Overflow用户
提问于 2018-06-04 16:14:28
回答 3查看 1.3K关注 0票数 2

为什么静态强制转换允许在指向派生对象或基的指针之间进行向上转换或向下转换,但如果是在char*和int*之间或相反的int*到char*之间进行转换,则存在编译错误?

在指向对象的不同指针之间进行转换,我认为也同样糟糕。

代码语言:javascript
运行
复制
// compiles fine
class Base {};
class Derived: public Base {};
Base * a = new Base;
Derived * bc = static_cast<Derived*>(a);

// Gives an invalid static cast error during compilation
char charVar = 8;
char* charPtr = &charVar;
int* intPtr = static_cast<int*>(charPtr);
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-06-04 17:12:25

C++是面向性能的。因此,只要有一些用例,您就可以获得性能,C++将允许您这样做。考虑std::vector:当然,可以通过函数at进行安全的元素访问,它为您进行范围检查。但是,如果您知道您的索引在范围内(例如,在一个for循环中),这些范围检查只是自重。因此,您还可以得到(不太安全的) operator[],它只是省略了这些检查。

类似地,如果您有一个Base类型的指针,它实际上可以指向Derived类型的对象。如果有疑问,您可以从dynamic_cast Base*Derived*。但这也带来了一些开销。但如果你能百分百肯定的话.子类实际上是什么,您想要这个开销吗?因为有一种自然的(甚至隐含的!)从Derived*Base*,我们想要一些低成本的回头路。

另一方面,完全不相关类型的指针(例如charint或两个无关的类)之间没有这样的自然转换,因此没有这样低成本的返回方式(与dynamic_cast相比,dynamic_cast当然也是不可用的)。在两者之间进行转换的唯一方法是reinterpret_cast

实际上,reinterpret_cast也是免费的,它只是将指针解释为一种不同的类型--所有的风险!如果需要的话,reinterpret_cast甚至可能失败(正确地防止“为什么不总是使用.”这个问题):

代码语言:javascript
运行
复制
class A { int a; };
class B { };
class C : public A, public B { };

B* b = new C();
C* c = reinterpret_cast<C*>(b); // FAILING!!!

从内存布局的角度来看,C看起来是这样的(即使对您隐藏):

代码语言:javascript
运行
复制
class C
{
    A baseA;
    B baseB; // this is what pointer b will point to!
};

显然,在C*B*之间进行转换时,我们会得到一个偏移量(无论是哪个方向),这是static_castdynamic_cast都考虑的,但reinterpret_cast没有考虑到。

票数 2
EN

Stack Overflow用户

发布于 2018-06-04 16:50:52

为什么静态演员允许一个上向演员..。

没有理由阻止上流社会。实际上,派生指针甚至可以隐式转换为基本指针--不需要强制转换(除非在有多个相同类型的基的复杂情况下除外)。派生类对象始终包含基类子对象。

Upcasting特别有用,因为它允许通过使用虚拟函数来实现运行时多态性。

或在指向派生对象或基对象的指针之间向下转换,如下所示

基指针可以指向派生对象的基子对象,这是向上转换的结果。比如这里:

代码语言:javascript
运行
复制
Derived d;
Base *b = &d;

在某些情况下,您可能希望访问指定指向的派生对象的成员。静态强制转换可以在不需要运行时类型信息的情况下实现这一点。

一般来说,编译器不可能(在编译时)找出指定对象的具体类型(即指针是否指向子对象,如果指针指向子对象,容器对象的类型是什么)。程序员有责任确保转换的要求得到满足。如果程序员无法证明其正确性,则编写静态强制转换是一个错误。

票数 2
EN

Stack Overflow用户

发布于 2018-06-04 16:51:09

这是因为你要做的是重新解释--其中有一个reinterpret_cast<>操作符。指针的static_cast<>只用于下浇铸

  1. 如果new_type是一个指针或对某个类D的引用,并且表达式的类型是一个指针或对它的非虚基B的引用,则static_cast执行向下转换。如果B是D的模棱两可的、不可访问的或虚拟的基(或虚拟基的基),则这种下拉式是不正确的。这样的static_cast不进行运行时检查以确保对象的运行时类型实际上是D,并且只有在其他方法(例如在实现静态多态时)保证了这个前提条件时才能安全地使用。可以用dynamic_cast进行安全的下传。

请参见:

用石膏吗?

有关何时使用每个铸造操作符的详细讨论。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50684795

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档