C++多接口(interface)继承和static_cast

标签 c++ inheritance casting multiple-inheritance

在下面的代码中:

Live

#include <iostream>
#include <thread>
#include <mutex>
#include <functional>

struct IView {
    virtual void setOnClick() = 0;
};
struct ITextView : IView {
    virtual void setText() = 0;
};
struct IButton : ITextView {
    virtual void setRadius() = 0;
};

struct View : IView {
    int i = 1;
    virtual void setOnClick() override {
        std::cout << "setting OnClick! i: " << i << std::endl;
    };
};

/// Works as is
/// But if make "TextView : View, ITextView" - have segfault on the run
struct TextView : ITextView, View {
    int j = 2;
    virtual void setText() override {
        std::cout << "setting text! i: " << i << " j: " << j << std::endl;
    };

    // forward IView
    virtual void setOnClick() override {
        View::setOnClick();
    }
};


int main() {
    TextView tv;

    void* ptr = &tv;    // I need to pass raw pointer, and then restore "interface" from it

    ITextView* itv = static_cast<ITextView*>(ptr);  // I don't need safety checks here
    itv->setOnClick();
    itv->setText();

    return 0;
}

如果我更改 TextView 的继承顺序,我将在 itv->setText(); 调用上出现段错误。

为什么重要?我可以在这里使用static_cast,还是我这里有UB?据我了解,dynamic_cast 只需要虚拟继承,而据我所知,情况并非如此。

最佳答案

就目前而言,您从 TextView* 隐式转换为 void*,然后从 void* 显式转换为 ITextView*。这些转换在从/向 void* 转换时不执行任何指针调整,因此您最终得到一个类型为 ITextView* 的指针,它实际上指向一个 TextView (不是它的 ITextView 子对象!):随之而来的是未定义的行为。

解决方案是始终void*的“两侧”使用完全相同的类型:

TextView tv;

void* ptr = static_cast<ITextView*>(&tv); // Adjust, then convert to void*

ITextView* itv = static_cast<ITextView*>(ptr);

关于C++多接口(interface)继承和static_cast,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47331823/

相关文章:

c++ - 构造函数引用参数导致段错误

c++ - 谷歌测试 : how to check a global C (C++) function was called

Java 字段继承和向上转型的奇怪行为

c - C 中的赋值错误

c++ - 在不相关的全等类之间进行转换

c++ - JDK9 Hotspot debug using gdb, causing SIGSEGV Segmentation fault in eclipse/Ubuntu 终端

c++ - Qt 4.8.2 与 GCC 4.7.0.1 不断崩溃

c++ - 使用 CRTP 的模板中的继承类型

Perl 不继承基本方法

将指针转换为左值