【问题标题】:virtual functions and static_cast虚函数和 static_cast
【发布时间】:2012-10-22 17:32:43
【问题描述】:

在多态类上使用 static_cast 后,我​​可以安全地调用虚函数,比如下面的代码还是 UB?

#include <iostream>

class Base
{
public:
   virtual void foo() { std::cout << "Base::foo() \n"; }
};

class Derived : public Base
{
public:
   virtual void foo() { std::cout << "Derived::foo() \n"; }
};

int main()
{
   Base* derived = new Derived;
   Derived* _1 = static_cast<Derived*>(derived);
   _1->foo();
}

【问题讨论】:

  • 我认为,如果您将foo() 设为非虚拟,这个问题会更有意义。

标签: c++ casting static-cast


【解决方案1】:

是的,你可以。尽管在您的具体示例中我没有看到这样做的意义。只是把它称为

derived->foo();

没有任何演员表会产生完全相同的效果。 IE。在这种情况下,某种static_cast 将由虚拟调用机制隐式执行。

请注意,您的 static_cast 不会以任何方式抑制呼叫的“虚拟”性质。

这实际上让我想知道你的问题到底是关于什么的。你为什么还要问这个?你想做什么?在您的代码示例中真正代表您正在尝试做什么?

【讨论】:

  • 为什么static_cast 不抑制呼叫的虚拟性质?
【解决方案2】:

如果编译器允许您 static_cast 并且在运行时对象的动态类型符合预期,那么是的,您可以。问题是你为什么要这么做……

【讨论】:

    【解决方案3】:

    是的,但正如其他人所说,您不需要将指针强制转换为派生类型来调用虚函数。

    但是,在处理继承类时,使用dynamic_cast 通常更安全。如果在运行时类型信息不正确,使用dynamic_cast 将产生正确的错误。

    Derived* d = dynamic_cast<Derived*>(derived); //safer, but still unnecessary in this situation 
    

    【讨论】:

      【解决方案4】:

      正如所写,这将起作用,主要是因为derived Derived*。所以,演员所做的就是告诉编译器你已经知道了什么。再说一次,即使没有静态演员表,您最终也会在输出中得到Derived::foo。所以,这有点毫无意义。尽管如此,您可能需要在绝对确定您知道变量的实际实例类型并且出于某种原因需要访问一些非虚拟成员的情况下执行此操作。例如,如果您使用的是设计不佳的类库...

      但是,一般来说,静态向下转换是个坏主意。您最终可能会尝试向下转换一个 不是 Derived* 的变量,在这种情况下,调用虚拟(或非虚拟)函数(或者,实际上,几乎所有非平凡的操作)导致未定义的行为。

      【讨论】:

        猜你喜欢
        • 2022-01-04
        • 2015-09-17
        • 2012-01-28
        • 1970-01-01
        • 2011-04-16
        • 1970-01-01
        • 2021-06-01
        • 2018-06-07
        • 2016-11-29
        相关资源
        最近更新 更多