这是有效的下投吗?
Is this a valid downcasting
我有一个 cpp 代码,其中类 c 派生自类 b,类 b 派生自类 a。
现在 B 类有一些公共数据成员。所以我正在堆上创建一个类 c 的实例,将其指针作为指向 a 的指针传递给另一个类,在那里它向下转换指向类 b 指针的指针,然后打印类 b 的公共变量。
这是有效的下投吗?我问是因为编译器的更改破坏了这个工作代码。
我在下面包含代码片段,这些代码片段捕获了我遇到的问题。
#include <iostream>
using namespace std;
class grand
{
};
class parent : public grand
{
public : parent(){i=0;}
int i;
parent(int j){ i = j;}
void set(int j){i = j;}
};
class child : public parent{
public: child(){};
};
void print ( grand* ptr)
{
parent *p = (parent*) ptr;
std::cout << std::endl << p->i << std::endl;
}
int main() {
// your code goes here
child c;
c.set(9);
print(&c);
return 0;
}
谢谢
这是有效的下投吗?
是的。您的演员表内部应用 static_cast
,根据 §5.2.9/11,这将为您提供正确的结果。如果 ptr
的参数不指向parent
,则强制转换的结果是未定义的 - 以下代码的执行也是如此。
通过dynamic_cast
对C++作品中的多态类型进行下铸 .上面的grand
类不是多态的 - 您必须至少添加一个虚拟析构函数来grand
才能使其成为多态的。否则,你将收到包含以下代码的编译器错误。
parent *p = dynamic_cast<parent*>(ptr); // Once grand is polymorphic...
并检查结果 p
是否为非零。只有这种方法才能(在运行时(显示演员表是否有效!所有其他值要么调用未定义的行为,要么调用未定义的非零值。
一些注意事项:
- 向下抛弃几乎总是设计不佳的标志。如果可能的话,避免使用,例如使用虚拟(打印(功能。
-
print
应该采用指向const
的指针,因为它不会修改任何数据成员。
你的代码,正如所写的,实际上是有效的,但我想做一堆观察。请注意,它之所以有效,只是因为传递给print
的对象是parent
或进一步派生的类。
然后请注意,由于您必须将其转换为print
函数,因此只需更改函数签名以采用parent
而不是grand
要安全得多,然后您不必担心转换。
然后请注意,问题的一个可能原因是,在执行强制转换的文件中,编译器看不到grand
和parent
之间的关系,因此 C 样式强制转换回退到reinterpret_cast
这不是您想要的。如果无法更改print
的签名,请至少将强制转换更改为 static_cast
(或可能更改为 dynamic_cast
,但不能在示例中执行此操作,因为类不是多态的(,以便编译器在看不到类关系时将无法编译。
如果出于某种原因在没有 RTTI(运行时类型信息(的情况下进行编译,则应应用 dynamic_cast
或至少应用static_cast
,而不是 C 样式转换。
你的C型强制转换与reinterpret_cast
相同,它基本上解释指向的内存,就好像在那里构造了一个parent
类型的对象一样。但是,每个编译器可能具有不同的派生类内存布局,因此在某些情况下可能有效,但不能保证。
- 欧拉项目#8答案是大以获得有效答案
- 调整大小后指向元素值的指针unordered_map有效?
- 为什么是0;C++中的有效语句
- 最高有效数字侧的第N位
- GCC对可能有效的代码抛出init list生存期警告
- 有效地使用std::unordered_map来插入或增加键的值
- c++中O(n^(1/3))中一个数的除数的有效计数
- 使用无符号字符数组有效存储内存
- 自定义先决条件对移动分配运算符有效吗
- 为什么将值返回函数传递给重载=运算符对运算符函数有效,而对其他运算符无效
- 有哪些有效的方法可以消除一组 100 万个字符串>重复数据?
- 为什么这种直接初始化有效?(C++17)
- 递归函数有效,但无法记忆
- 在C++中初始化向量映射的最有效方法
- 如果变量名称不跟在 char* 后面,const char* 是否有效?
- 钳制迭代器是否有效
- 如何有效地在 std::vector 中插入一对?
- C++模板 t 不是有效的模板类型
- 检查由括号、方括号和大括号组成的一组方括号是否有效?
- 将此布尔值传递给此函数的最有效方法是什么?