[英]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);
现在, dr
和dp
指向上面相同的d
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.