我需要知道在什么条件下可以使用 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 向下转型的现有线程,但没有一个真正回答在哪些条件下可以避免未定义的行为。
但是如果最初指向父类对象的指针从未使用子类的任何成员怎么办?在这种情况下使用 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 原则。