C++ 这是一个有效的下调吗
我有一个cpp代码,其中c类派生自b类,b类派生自a类 现在b类有一些公共数据成员。所以我在堆上创建了一个c类的实例,将它的指针作为指向a的指针传递给另一个类,然后向下转换指向b类指针的指针,然后打印b类的公共变量 这是一个有效的下调。我这样问是因为编译器的更改破坏了这段工作代码 我在下面的代码片段中包含了我遇到的问题C++ 这是一个有效的下调吗,c++,pointers,C++,Pointers,我有一个cpp代码,其中c类派生自b类,b类派生自a类 现在b类有一些公共数据成员。所以我在堆上创建了一个c类的实例,将它的指针作为指向a的指针传递给另一个类,然后向下转换指向b类指针的指针,然后打印b类的公共变量 这是一个有效的下调。我这样问是因为编译器的更改破坏了这段工作代码 我在下面的代码片段中包含了我遇到的问题 #include <iostream> using namespace std; class grand { }; class parent : public g
#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;
}
#包括
使用名称空间std;
大班
{
};
班级家长:公共大
{
public:parent(){i=0;}
int i;
父(intj){i=j;}
空集(intj){i=j;}
};
类子:公共父类{
公共:child(){};
};
作废打印(大*ptr)
{
父*p=(父*)ptr;
标准::cout
这是一个有效的下调
是的。您的强制转换在内部应用了静态\u强制转换
,根据§5.2.9/11,这将为您提供正确的结果。如果ptr
的参数没有指向父级
,则强制转换的结果是未定义的,因此将无法执行以下代码
> C++中的多态类型的向下投射是通过<代码>动态> Studio。你的<代码> Grave<代码>类不是多态的-你必须至少添加一个虚拟析构函数到Grime<代码>使其多态,否则你会得到以下代码的编译错误。
parent *p = dynamic_cast<parent*>(ptr); // Once grand is polymorphic...
parent*p=dynamic_cast(ptr);//一旦grand是多态的。。。
并检查结果p
是否为非零值。只有此方法(在运行时)才能显示强制转换是否有效!所有其他方法要么调用未定义的行为,要么调用未定义的非零值
一些注意事项:
- 向下投射几乎总是设计不好的标志。如果可能的话,使用虚拟(打印)功能避免向下投射
print
应该使用指向const
的指针,因为它不会修改任何数据成员
这是一个有效的下调
是的。您的强制转换在内部应用了静态\u强制转换
,根据§5.2.9/11,这将为您提供正确的结果。如果ptr
的参数没有指向父级
,则强制转换的结果是未定义的,因此将无法执行以下代码
> C++中的多态类型的向下投射是通过<代码>动态> Studio。你的<代码> Grave<代码>类不是多态的-你必须至少添加一个虚拟析构函数到Grime<代码>使其多态,否则你会得到以下代码的编译错误。
parent *p = dynamic_cast<parent*>(ptr); // Once grand is polymorphic...
parent*p=dynamic_cast(ptr);//一旦grand是多态的。。。
并检查结果p
是否为非零值。只有此方法(在运行时)才能显示强制转换是否有效!所有其他方法要么调用未定义的行为,要么调用未定义的非零值
一些注意事项:
- 向下投射几乎总是设计不好的标志。如果可能的话,使用虚拟(打印)功能避免向下投射
print
应该使用指向const
的指针,因为它不会修改任何数据成员
您编写的代码实际上是有效的,但我想做一些观察。请注意,它是有效的,因为您传递给print
的对象是父类或进一步派生的类
然后请注意,由于您必须将其转换为print
函数,因此只需将函数签名更改为采用父级
而不是grand
,这样您就不必担心转换问题
然后请注意,问题的一个可能原因是,在执行转换的文件中,编译器看不到grand
和parent
之间的关系,因此您的C样式转换返回到reinterpret\u cast
,这不是您想要的。如果您无法更改print
的签名,至少更改e cast到静态\u cast
(或者可能是动态\u cast
,但在示例中不能这样做,因为类不是多态的)因此,编译器在看不到类关系时将无法编译。您编写的代码实际上是有效的,但我想做一些观察。请注意,它是有效的,因为您传递给print
的对象是父类或进一步派生的类
然后请注意,由于您必须将其转换为print
函数,因此只需将函数签名更改为采用父级
而不是grand
,这样您就不必担心转换问题
然后请注意,问题的一个可能原因是,在执行转换的文件中,编译器看不到grand
和parent
之间的关系,因此您的C样式转换返回到reinterpret\u cast
,这不是您想要的。如果您无法更改print
的签名,至少更改e cast到静态\u cast
(或者可能是动态\u cast
,但在示例中不能这样做,因为类不是多态的)因此,编译器在看不到类关系时将无法编译。如果出于某种原因编译时没有RTTI(运行时类型信息),则应应用动态\u cast
或至少应用静态\u cast
您的C风格强制转换与重新解释强制转换相同,它本质上解释指向的内存,就好像父类类型的对象会在那里构造一样。但是,每个编译器可能有不同的派生类内存布局,因此在某些情况下可以工作,但没有保证。您应该应用dynamic\u cast
o,而不是C型强制转换