本文介绍了从基类转换为派生类是未定义的行为吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了一个问题,即强制转换为派生类可以解决该问题。我在S.O上找到了一个答案,说它可以导致UB,对其进行测试,编译并可以正常工作。它是未定义的行为吗?

I've encountered myself in a problem where casting to the derived class would solve the problem. I've found an answer on S.O that says it can lead to UB, testing it, it both compiled and worked correctly. Is it undefined behavior? If it is what would be a correct approach to this problem?

class A
{
public:
    A(){};
    ~A(){}
};

class B : public A
{
public:
    B(){};
    ~B(){}
    void Show() { std::cout << "Show" << std::endl; }
};

int _tmain(int argc, _TCHAR* argv[])
{
    A a;
    B* b = static_cast<B*>(&a);
    b->Show();

    return 0;
}


推荐答案

只要指向基本类型实际上指向派生类型的实例,那么根据C ++标准,这种用法并不是未定义的。 但是 ,在您的代码示例中,指针 b 并不指向的实例B 或其任何派生类型(没有),它指向 A 的实例。因此,您的代码实际上确实调用了未定义的行为。

As long as the pointer to a base type actually points to an instance of a derived type, then such usage is not undefined according to the C++ standard. However, in your code sample, the pointer b does not point to an instance of B or any of its derived types (which there are none), it points to an instance of A. So your code does in fact invoke undefined behavior.

某些代码可以正确编译并正常工作的事实并不排除可能性调用未定义行为的代码,因为未定义行为包括似乎可以正常工作。之所以要避免未定义的行为,是因为无法保证它在下次调用UB时将以相同的方式起作用。

The fact that some code compiles and works correctly does not rule out the possibility of code invoking undefined behavior, because undefined behavior includes "appears to work". The reason why you should avoid undefined behavior is because there's no guarantee that it will work the same way the next time you invoke UB.

在您的示例中,这是未定义的行为。正确的方法取决于您的代码实际应该执行的操作,因为您提供的示例充其量只是一个学术示例。

In your sample, yes, it is undefined behavior. The correct approach would depend on what your code is actually supposed to do, as the example you provide is an academic example at best.

为清楚起见,请进行以下修改到 main()函数具有明确定义的行为,并且C ++标准明确允许该行为:

To make it clear, the following modification to your main() function has well-defined behavior and is explictly allowed by the C++ standard:

B objectB;
A* ptrA = &objectB;

B* b = static_cast<B*>(ptrA);
b->Show();

在这里,它的定义很明确,因为指针 ptrA 实际上指向 B 的实例,即使指针本身的类型为 A * 。在上面的示例中,将 A * 转换为 B * ,然后调用 B 在强制转换指针上的功能将起作用。区别在于,在您问题的示例中, b 实际上并不指向 B 的实例。

Here, it's well defined because the pointer ptrA actually points to an instance of B, even though the pointer itself has type A*. In the above example, casting from A* to B* then invoking one of B's functions on the casted pointer will work. The difference is that in the example in your question, b does not actually point to an instance of B.

相关条款(强调我的意思):

The relevant clause (emphasis mine):

这篇关于从基类转换为派生类是未定义的行为吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 09:11