Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/159.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 静态强制转换允许转换对象指针,但不允许转换整数_C++_Casting_Static Cast - Fatal编程技术网

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

C++ 静态强制转换允许转换对象指针,但不允许转换整数,c++,casting,static-cast,C++,Casting,Static Cast,为什么静态强制转换允许在指向派生对象或基对象的指针之间进行向上或向下转换,如下所示,但是在char*和int*之间进行强制转换,或者反之亦然,int*到char*之间存在编译错误 我认为,在指向对象的不同指针之间进行强制转换同样糟糕 // compiles fine class Base {}; class Derived: public Base {}; Base * a = new Base; Derived * bc = static_cast<Derived*>(a); /

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

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

// 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);
为什么静态投射允许向上投射

没有理由阻止上抛。事实上,派生指针甚至可以隐式地转换为基指针——除了存在多个相同类型的基的复杂情况外,不需要强制转换。派生类对象始终包含基类子对象

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

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

由于向上转换,基指针可能指向派生对象的基子对象。比如这里:

Derived d;
Base *b = &d;
在某些情况下,您可能希望访问已知被指向的派生对象的成员。静态强制转换使这成为可能,而无需花费运行时类型信息

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

为什么静态投射允许向上投射

没有理由阻止上抛。事实上,派生指针甚至可以隐式地转换为基指针——除了存在多个相同类型的基的复杂情况外,不需要强制转换。派生类对象始终包含基类子对象

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

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

由于向上转换,基指针可能指向派生对象的基子对象。比如这里:

Derived d;
Base *b = &d;
在某些情况下,您可能希望访问已知被指向的派生对象的成员。静态强制转换使这成为可能,而无需花费运行时类型信息


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

这是因为您试图做的是一个重新解释,其中有一个操作符。指针的静态类型转换为:

如果new_type是指向某个类D的指针或引用,而表达式的类型是指向其非虚拟基B的指针或引用,则static_cast将执行向下转换。如果B是不明确的、不可访问的或虚拟基或虚拟基D的基,则此向下转换是错误的。此类静态向下转换不进行运行时检查以确保对象的运行时类型实际上是D,并且只有在通过其他方式(如在实现静态多态性时)保证此前提条件时,才能安全使用。安全下行可以通过动态下行来完成。 见:


有关何时使用每个强制转换操作符的详细讨论。

这是因为您试图做的是一个重新解释,其中有一个操作符。指针的静态类型转换为:

如果new_type是指向某个类D的指针或引用,而表达式的类型是指向其非虚拟基B的指针或引用,则static_cast将执行向下转换。如果B是不明确的、不可访问的或虚拟基或虚拟基D的基,则此向下转换是错误的。此类静态向下转换不进行运行时检查以确保对象的运行时类型实际上是D,并且只有在通过其他方式(如在实现静态多态性时)保证此前提条件时,才能安全使用。安全下行可以通过动态下行来完成。 见:


有关何时使用每个强制转换操作符的详细讨论。

C++非常注重性能。所以只要有一些用例可以让你获得性能,C++会允许你去做。考虑STD::向量:当然,有一个安全的元素通过函数访问,它为你做范围检查。但如果你知道你的指数在e范围内。G在for循环中,这些范围检查只不过是自重。因此,您还得到了不太安全的运算符[],它忽略了这些检查

类似地,如果您有一个Base类型的指针,实际上它可以指向派生类型的对象。如有疑问,, 您可以将动态_从基*转换为派生*。但这会带来一些开销。但是如果你百分之百肯定的话。。。子类实际上是什么,您想要这个开销吗?因为有一种自然甚至含蓄!从派生*到基本*,我们想要一些低成本的方法

另一方面,在完全不相关类型(如char和int)或两个不相关类的指针之间没有这样的自然转换,因此与动态转换(当然也不可用)相比,没有这样低成本的方法。在两者之间转换的唯一方法是重新解释演员阵容

实际上,reinterpret_cast也没有成本,它只是将指针解释为一种不同的类型——有所有风险!如果需要一个静态的强制转换来防止这个问题,为什么不总是使用…,那么重新解释强制转换甚至可能失败:

class A { int a; };
class B { };
class C : public A, public B { };

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

显然,在C*和B*任意方向之间进行转换时,我们都会得到一个偏移量,静态转换和动态转换都会考虑这个偏移量,但重新解释转换时不会考虑这个偏移量…

C++非常注重性能。所以只要有一些用例可以让你获得性能,C++会允许你去做。考虑STD::向量:当然,有一个安全的元素通过函数访问,它为你做范围检查。但如果你知道你的指数在e范围内。G在for循环中,这些范围检查只不过是自重。因此,您还得到了不太安全的运算符[],它忽略了这些检查

类似地,如果您有一个Base类型的指针,实际上它可以指向派生类型的对象。如果有疑问,您可以将动态_从基*转换为派生*。但这会带来一些开销。但是如果你百分之百肯定的话。。。子类实际上是什么,您想要这个开销吗?因为有一种自然甚至含蓄!从派生*到基本*,我们想要一些低成本的方法

另一方面,在完全不相关类型(如char和int)或两个不相关类的指针之间没有这样的自然转换,因此与动态转换(当然也不可用)相比,没有这样低成本的方法。在两者之间转换的唯一方法是重新解释演员阵容

实际上,reinterpret_cast也没有成本,它只是将指针解释为一种不同的类型——有所有风险!如果需要一个静态的强制转换来防止这个问题,为什么不总是使用…,那么重新解释强制转换甚至可能失败:

class A { int a; };
class B { };
class C : public A, public B { };

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

显然,当在C*和B*任意方向之间进行转换时,我们会得到一个偏移量,这是静态转换和动态转换都考虑的,但不是通过重新解释转换…

在指向对象的不同指针之间进行转换也是一样糟糕的,我相信你为什么会这么认为?基*和派生*之间存在关系。char*和int*@Engineer999之间不存在这种很难检测的关系。是的,向下投射可能会引起问题,但如果我知道我从衍生*到基础*我应该可以直接返回,而不必支付动态_投射的费用。C++没有很多的手握,所以不幸的是,你会有很多方法来射击自己的脚。我投票赞成关闭这个问题。问为什么会有这样的功能,而这个类似的功能却没有?我同意YSC的观点——也许上面提到的问题并不是我们想要的问题?问为什么静态_cast允许{一件事}而不允许{不同的事}是不可能有一个超出它的答案的,这个问题被提出并被投票到标准中。在指向对象的不同指针之间进行强制转换也同样糟糕,我相信你为什么相信?基*和派生*之间有关系。char*和int*@Engineer999之间不存在这种很难检测的关系。是的,向下投射可能会引起问题,但如果我知道我从衍生*到基础*我应该可以直接返回,而不必支付动态_投射的费用。C++没有很多的手握,所以不幸的是,你会有很多方法来射击自己的脚。我投票赞成关闭这个问题。问为什么会有这样的功能,而这个类似的功能却没有?我同意YSC的观点——也许上面提到的问题并不是我们想要的问题?问为什么静态_cast允许{一件事}而不允许{不同的事}是不太可能有一个超出它的答案的,这是被提议并投票进入标准的。好的,谢谢。我看到了将基指针强制转换为派生指针以用于虚拟函数的动态绑定的好处,在这种情况下,基指针实际上将指向完整的派生对象,但相反,派生指针指向基对象?@Engineer999您不能将指向派生类型的指针指向inst
基本类型的属性。当你知道一个指针的基点实际上指向一个派生类型的实例时,你只会做这个转换。@弗兰Cou.OISANDURIX,但是StistaCype允许它吗?@ CealErr999 StistaCype允许你让编译器进行转换,但这并不意味着结果是合法的C++。您的工作是确保要转换的指针实际上指向一个对象,该对象可以由您要转换的指针类型合法地指向。在C++中,理解编译器是非常重要的,因为编译器允许它不一定使它合法。@工程实例99,前提是错误的,该转换是无效的,它永远不会有用。这是未定义的行为,编译器不需要检测或报告此错误。好的,谢谢。我看到了将基指针强制转换为派生指针以用于虚拟函数的动态绑定的好处,在这种情况下,基指针实际上将指向完整的派生对象,但相反,是否有指向基对象的派生指针?@Engineer999不能有指向指向基类型实例的派生类型指针。当你知道一个指针的基点实际上指向一个派生类型的实例时,你只会做这个转换。@弗兰Cou.OISANDURIX,但是StistaCype允许它吗?@ CealErr999 StistaCype允许你让编译器进行转换,但这并不意味着结果是合法的C++。您的工作是确保要转换的指针实际上指向一个对象,该对象可以由您要转换的指针类型合法地指向。在C++中,理解编译器是非常重要的,因为编译器允许它不一定使它合法。@工程实例99,前提是错误的,该转换是无效的,它永远不会有用。这是未定义的行为,编译器不需要检测或报告此错误。