繁体   English   中英

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

[英]Why does static_cast require pointers or references?

最近,我不得不使用static_cast将父类强制转换为子类,因为我知道对象实例就是该子类。 我基于if条件知道这一点。

像这样:

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

我的问题是:为什么static_cast总是需要指针? 当我尝试使用非指针变量时,这不起作用。 原始数据类型似乎是一个例外。

这是因为每个指针都可以转换为void *吗? 那是static_cast的工作方式吗?

编辑:我忘了提及它与引用一起使用。 因此,当前提出的问题是错误的。 将问题重新定义为“为什么static_cast为什么需要指针或引用?”

为什么static_cast总是需要指针?

运算符static_cast不需要指针,也不需要引用。

C ++标准n3337§5.2.9 / 4:

否则, 如果声明T t(e) ,则可以使用static_cast<T>(e)形式的static_cast<T>(e)将表达式e显式转换为T类型。 对于某些发明的临时变量t (8.5), 其格式正确 这种显式转换的效果与执行声明和初始化,然后将临时变量用作转换结果的效果相同。 当且仅当初始化将其用作glvalue时,才将表达式e用作glvalue。

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

当我尝试使用非指针变量时,这不起作用。

例如? 您如何尝试的? 如果你的意思是

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

然后这称为切片 ,这意味着p将仅从c中获取来自父类的数据(由于父子添加到派生的父数据中,父类的对象又如何接收子部分?)。

原因是:否,它可以是指针或引用。 这与以下问题有关:

 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.

基本上,您不能在不冒切片风险的情况下,通过派生类对基类进行实例化。 但是引用/指针是另一回事。 在这种情况下,您只是在解释如何解释所指向的内存。 在这种情况下,静态投射实际上不执行任何操作! 由于C ++类的布局方式(有意地),从基类继承的所有内容都具有从0偏移量到sizeof(Base)的相同内存布局。 只有在那之后,您才添加派生的东西。

为什么static_cast总是需要指针?

好吧,并非总是如此。 如您所指出的,以下是可能的:

int i = static_cast<int>(3.14);

static_cast也可以用于在引用之间进行转换,就像使用指针一样。

但是,您必须考虑以下因素:在两种类型之间进行转换时,您可能会丢失信息。 假设您有一个Animal类,另一个是Dog类,它恰好继承自它。 这是什么意思?

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

您是用Dog创建Animal的,但是Dog的特定信息将被丢弃。 这称为切片

指针之间的转换通常只涉及重新解释内存。 基础对象保持不变。

本质上, static_cast<>总是创建带有尖括号之间提供的类型的新内容。 考虑:

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

现在,以下代码将无法编译:

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

原因很简单:此代码尝试创建derived新实例,并将base传递给其构造函数。 如果derived有该构造函数,它将进行编译。 例如:

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

但是现在您有了一个临时目录,该临时目录将立即被删除。

显然,您不想在这里创建新的derived实例,但是要到达派生实例,您的基础就是其中的一部分。 在执行转换时,您需要创建对derived的引用或指针,而不是它的全新实例。 以下将起作用:

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

现在, drdp指向上面相同的d

暂无
暂无

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

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