C++ 这是一个有效的下调吗

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

我有一个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;
}
#包括
使用名称空间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型强制转换