简体   繁体   English

在这种情况下,有没有比dynamic_cast更好的解决方案?

[英]Is there a better solution than dynamic_cast in that case?

I'm trying to make platform independent code so I'm using OOP. 我试图制作独立于平台的代码,所以我在使用OOP。 For example, on Windows, Mac OS X, and Linux you can have windows, but on android you have views so I'm trying to abstract this. 例如,在Windows,Mac OS X和Linux上,您可以拥有Windows,但是在android上,您可以拥有视图,因此我尝试对此进行抽象。

I first made a class to represent a window or a view which I called view: 我首先创建一个类来表示窗口或视图,我称之为视图:

class View
{
public:
    virtual ~View()
    {}

    virtual void display() = 0;
    virtual void hide() = 0;
};

Now the problem is that on Android, there is no title for views while on Windows there are so I decided to create another class: 现在的问题是,在Android上没有视图的标题,而在Windows上则没有视图的标题,所以我决定创建另一个类:

class NameableView : public View
{
public:
    virtual void setName(const std::string& name) 
};

And then finally implement the classes: 然后最后实现这些类:

class WindowsView : public NameableView
{
    /* Windows implementation */
}

class AndroidView : public View
{
    /* Android implementation */
}

Then I need to make some code which sets the name for a view only if it is possible (if it inherits from the NameableView class). 然后,我需要制作一些代码,仅在可能的情况下(如果它继承自NameableView类),为视图设置名称。

So how can I solve this problem? 那么我该如何解决这个问题呢? I first thought about dynamic_cast but I often hear that having too much dynamic_cast is an indication of a design problem. 我首先想到了dynamic_cast但是我经常听到, dynamic_cast过多表明存在设计问题。 I'm a beginner in C++ so maybe I didn't think the right way and I should change the whole design. 我是C ++的初学者,所以也许我没有想到正确的方法,我应该更改整个设计。

I'm trying to make platform independent code so I'm using OOP. 我试图制作独立于平台的代码,所以我在使用OOP。

This is not an optimal approach - polymorphic hierarchies and virtual functions allow different concrete object types that inherit from the same interface to behave differently at run-time , but you know the platform you're going to target at compile-time . 这不是最佳方法-多态层次结构和virtual函数允许从同一接口继承的不同具体对象类型在运行时表现不同,但是您知道要在编译时定位的平台。

What you should instead do is use static polymorphism and CRTP to provide a common interface that every concrete per-platform implementation must satisfy. 您应该做的是使用静态多态性和CRTP提供每个通用的每平台实现都必须满足的通用接口。

template <typename TDerived>
struct View
{
    void display() { static_cast<TDerived&>(*this).display(); }
    void hide() { static_cast<TDerived&>(*this).hide(); }

    constexpr bool supportsSetView() const
    {
        return static_cast<TDerived&>(*this).supportsSetView();
    }
};

In the case of setName , you should provide a supportsSetView check on every platform that returns true at compile-time if the view can be named. 对于setName ,您应该在每个平台上都提供一个supportsSetView检查,如果可以命名该视图,则在编译时返回true Then you perform that check on the caller side and only invoke setName if the check passes. 然后,您在调用方执行该检查,并且仅在检查通过时才调用setName

Example usage: 用法示例:

#if defined(PLATFORM_ANDROID)
struct AndroidView 
{
    // ...
    constexpr bool supportsSetView() const { return false; }
};   

using MyView = View<AndroidView>;
#else if defined(PLATFORM_WINDOWS)
struct WindowsView 
{
    // ...
    constexpr bool supportsSetView() const { return true; }
    void setName(std::string x) { /* ... */ }
};

using MyView = View<WindowsView>;
#else
#error "Unsupported platform."
#endif

Caller side: 来电方:

MyView currentView;

if constexpr(currentView.supportsSetView())
{
    currentView.setName("something");
}

As if constexpr(...) 's evaluation occurs at compile-time, the code will only call setName if it is supported by MyView . 就像if constexpr(...)的求值发生在编译时一样,如果MyView支持,则代码只会调用setName

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM