C++多接口继承和static_cast

tow*_*120 1 c++ inheritance casting multiple-inheritance

在以下代码中:

生活

#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;
}
Run Code Online (Sandbox Code Playgroud)

如果我更改了TextView继承顺序,我将在itv->setText();调用时遇到段错误.

它为什么如此重要?我可以static_cast在这里使用,或者我在这里有UB吗?据我所知,dynamic_cast只有虚拟继承需要,而且,正如我所知,这不是那种情况.

Que*_*tin 5

就目前而言,您可以隐式转换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);
Run Code Online (Sandbox Code Playgroud)