简体   繁体   English

为什么static_cast需要指针或引用?

[英]Why does static_cast require pointers or references?

I recently had a situation where i had to use static_cast to cast a parent class to a child class, because i knew the object instance was that child class. 最近,我不得不使用static_cast将父类强制转换为子类,因为我知道对象实例就是该子类。 I knew this based on an if condition. 我基于if条件知道这一点。

Something like this: 像这样:

parent* foo;
child* bar;
if(foo is instance of child class)
   bar = static_cast<child*>(foo)

My question is: Why does static_cast always require pointers? 我的问题是:为什么static_cast总是需要指针? This did not work when i tried it with non-pointer variables. 当我尝试使用非指针变量时,这不起作用。 An exception seems to be primitive data types. 原始数据类型似乎是一个例外。

Is this because every pointer can be cast as a void*? 这是因为每个指针都可以转换为void *吗? Is that how static_cast works? 那是static_cast的工作方式吗?

Edit: I forgot to mention that it works with references. 编辑:我忘了提及它与引用一起使用。 So the question, as it is currently framed, is wrong. 因此,当前提出的问题是错误的。 Reframing the question to "Why does static_cast require pointers or references?" 将问题重新定义为“为什么static_cast为什么需要指针或引用?”

Why does static_cast always require pointers? 为什么static_cast总是需要指针?

The operator static_cast doesn't require pointers, nor references. 运算符static_cast不需要指针,也不需要引用。

C++ Standard n3337 § 5.2.9/4: C ++标准n3337§5.2.9 / 4:

Otherwise, an expression e can be explicitly converted to a type T using a static_cast of the form static_cast<T>(e) if the declaration T t(e) ; 否则, 如果声明T t(e) ,则可以使用static_cast<T>(e)形式的static_cast<T>(e)将表达式e显式转换为T类型。 is well-formed , for some invented temporary variable t (8.5). 对于某些发明的临时变量t (8.5), 其格式正确 The effect of such an explicit conversion is the same as performing the declaration and initialization and then using the temporary variable as the result of the conversion. 这种显式转换的效果与执行声明和初始化,然后将临时变量用作转换结果的效果相同。 The expression e is used as a glvalue if and only if the initialization uses it as a glvalue. 当且仅当初始化将其用作glvalue时,才将表达式e用作glvalue。

parent* foo;
child* bar;
if(foo is instance of child class)
   bar = static_cast<child*>(foo)

This did not work when i tried it with non-pointer variables. 当我尝试使用非指针变量时,这不起作用。

For example? 例如? How you tried it? 您如何尝试的? If you mean 如果你的意思是

child c;
parent p = static_cast<parent>( c);

then this is called slicing , what means p will only get those data from c which comes from parent class (how could object of class parent receive also child part, since child is addition to derived parent data?). 然后这称为切片 ,这意味着p将仅从c中获取来自父类的数据(由于父子添加到派生的父数据中,父类的对象又如何接收子部分?)。

The reason is: it doesn't, it can be pointers or references. 原因是:否,它可以是指针或引用。 This has to do with the following problem: 这与以下问题有关:

 struct Base
 {

 };


 struct Derived : public Base
 {
   int A;
 };

 //sizeof(Base)==0
 //sizeof(Derived)==4
 Base B;
 Derived X;
 X.A = 10;
 B=X;//what happens to Derived::A? There is no space to put it. This is called slicing.

Basically, you cannot make an INSTANCE of a based class with a derived class without risking slicing. 基本上,您不能在不冒切片风险的情况下,通过派生类对基类进行实例化。 But references/pointers are another matter. 但是引用/指针是另一回事。 in that case, you are just interpreting how the memory pointed to is interpreted. 在这种情况下,您只是在解释如何解释所指向的内存。 Static cast doesn't actually do any operations in this case! 在这种情况下,静态投射实际上不执行任何操作! Because of the way C++ classes are layed out (intentionally) everything that inherits from a Base class has t'she same memory layout from offset of 0 to sizeof(Base). 由于C ++类的布局方式(有意地),从基类继承的所有内容都具有从0偏移量到sizeof(Base)的相同内存布局。 Only after that do you add Derived stuff. 只有在那之后,您才添加派生的东西。

Why does static_cast always require pointers? 为什么static_cast总是需要指针?

Well, not always. 好吧,并非总是如此。 As you pointed out, the following is possible: 如您所指出的,以下是可能的:

int i = static_cast<int>(3.14);

static_cast can also be used to convert between references, just like with pointers. static_cast也可以用于在引用之间进行转换,就像使用指针一样。

However, you have to take the following into account: When converting between two types, you can loose information. 但是,您必须考虑以下因素:在两种类型之间进行转换时,您可能会丢失信息。 Suppose you have a class Animal and another class Dog that happens to inherit from it. 假设您有一个Animal类,另一个是Dog类,它恰好继承自它。 What would this mean? 这是什么意思?

Dog d;
Animal a = static_cast<Animal>(d);

You're creating an Animal out of a Dog , but the Dog 's specific information will be thrown away. 您是用Dog创建Animal的,但是Dog的特定信息将被丢弃。 This is called slicing . 这称为切片

Casting between pointers usually just involves reinterpreting memory; 指针之间的转换通常只涉及重新解释内存。 the underlying object stays the same. 基础对象保持不变。

In essence static_cast<> always creates something new with type provided between the angle brackets. 本质上, static_cast<>总是创建带有尖括号之间提供的类型的新内容。 Consider: 考虑:

class base { int x; };
class derived: public base { int y; };

Now the following code will not compile: 现在,以下代码将无法编译:

base *b;
derived *d = &static_cast<derived>(*b);   // wrong

The reason is simple: this code tries to create new instance of derived and pass a base to its constructor. 原因很简单:此代码尝试创建derived新实例,并将base传递给其构造函数。 It would compile if derived had the constructor for that. 如果derived有该构造函数,它将进行编译。 For example: 例如:

class derived: public base
{
  int y;
  derived(const base &){}
};

But now you have a temporary that is going to be deleted immediately. 但是现在您有了一个临时目录,该临时目录将立即被删除。

Obviously you don't want to create new derived instances here, but to reach the derived instance your base is part of. 显然,您不想在这里创建新的derived实例,但是要到达派生实例,您的基础就是其中的一部分。 You need to create either a reference or a pointer to derived when performing the cast, and not a whole new instance of it. 在执行转换时,您需要创建对derived的引用或指针,而不是它的全新实例。 The following is going to work: 以下将起作用:

derived d;
base *bp = &d;
base &br =  d;
derived &dr = static_cast<derived &>(br);
derived *dp = static_cast<derived *>(bp);

Now both dr and dp point to the same d above. 现在, drdp指向上面相同的d

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM