为什么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:
否则,表达式 e 可以显式转换为类型 T 使用表单static_cast
static_cast<T>(e)
如果声明T t(e)
;对于某些发明的临时变量t
(8.5) 来说,格式良好。 这种显式转换的效果与执行 声明和初始化,然后使用临时 变量作为转换的结果。表达式 e 用作 当且仅当初始化将其用作 GL值时,GL值。
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 获取来自父类的数据(类父的对象怎么可能也接收子部分,因为 Child 是派生父数据的加法?
从本质上讲,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
。
原因是:它没有,它可以是指针或引用。这与以下问题有关:
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
的特定信息将被丢弃。这称为切片。
指针之间的转换通常只涉及重新解释内存;底层对象保持不变。
- 如何使用基类指针引用派生类成员
- 将常量指针引用绑定到非常量指针
- 如果非动态变量被指针引用,何时超出范围?
- 转换指针引用的字符串
- 指针引用的生存期(以 C++为单位)
- 从 unique_ptr::get 发送指针作为指针引用进入函数
- 指针/引用的 CLion 格式
- 使用模板专用化来比较指针引用
- 如何保存指向抽象基类的指针/引用,但在 c++ 中仍然可以复制
- C++初始化指针/引用/复制细微差别
- 用数组或指针引用函数?
- 指针范围问题和返回类中封装的指针向量内的指针引用
- 强制转换为指针引用是否会导致未定义的行为
- 访问由 void 指针引用的结构的成员
- C 为什么当先前的步骤引发异常时,std :: shared_ptr的指针引用会被破坏
- 动态指针引用数组由三元运算符返回值,但有异常
- 悬空指向 int 和 char* 常量的指针/引用
- C++ 二维数组和指针引用
- 通过使用指针/引用,在C++中使用向量加快计算速度
- C++非类型模板模板到函数指针/引用