什么时候可以安全地使用 static_cast 在 C++ 中进行向下转型?

问题描述 投票:0回答:1

我需要知道在什么条件下可以使用 static_cast 以便将父类指针转换为子类指针而不会导致未定义的行为。 通常建议使用dynamic_cast进行安全向下转型,但是如果最初指向父类对象的指针从不使用子类的任何成员怎么办?在这种情况下使用 static_cast 安全吗?

如果是,那么以下示例代码不应导致任何未定义的行为。

示例:

struct Parent {
    int i = 3;
    void print() { std::cout << i << std::endl; }
};
struct Child : Parent {
    double d = 5;
    void change() { i *= 2; }
};

int main() {
    Parent* pParent = new Parent;
    Child* pChild = static_cast<Child*>(pParent);
    pChild->print(); //should be ok
    //std::cout << pChild->d << std::endl; //undefined behavior
    //pChild->change(); //does this lead to an undefined behavior?
}

额外问题: 如果子类中的成员函数仅使用父类中的成员,那么使用该函数是否安全?在上面的例子中,这意味着使用

pChild->change();

目标: 我的目标是避免dynamic_cast以保证性能安全。只要我知道如何避免未定义的行为,我肯定愿意冒着使用 static_cast 的风险。 已经有关于使用 static_cast 向下转型的现有线程,但没有一个真正回答在哪些条件下可以避免未定义的行为。

c++ undefined-behavior dynamic-cast downcast static-cast
1个回答
0
投票

但是如果最初指向父类对象的指针从未使用子类的任何成员怎么办?在这种情况下使用 static_cast 安全吗?

不,该行为仍未定义。

如果是,那么以下示例代码不应导致任何未定义的行为。

该示例具有未定义的行为,因为

pParent
指向
Parent
类型的对象,该对象不是某个
Child
对象的基类子对象,根据标准,这会导致
static_cast<Child*>(pParent)
具有未定义的行为。

额外问题:如果子类中的成员函数仅使用父类中的成员,那么使用该函数是否安全?

不,转换本身,即使根本不使用结果,也具有未定义的行为。

目标:我的目标是避免dynamic_cast以保证性能安全。

您可以在

static_cast
不会返回空指针的情况下安全地使用
dynamic_cast
。在其他情况下,static_cast 将具有未定义的行为。这正是
为什么
static_cast 更快。
如果在创建 

Child

对象时未将

Parent
对象创建为基类子对象,则无法获取指向
Child
的指针。语言根本不允许这样做。要以任何方式操作
Child*
,您需要先创建一个
Child
对象。
通常最好使用合适的

virtual

函数接口而不是

dynamic_cast
。这不仅性能更高,而且不会像
dynamic_cast
那样违反 OOP 原则。
    

© www.soinside.com 2019 - 2024. All rights reserved.