2017-02-12 3 views
2

Ich versuche plattformunabhängigen Code zu machen, also verwende ich OOP. Zum Beispiel können Sie unter Windows, Mac OS X und Linux Fenster haben, aber auf Android haben Sie Ansichten, so dass ich versuche, dies zu abstrahieren.Gibt es in diesem Fall eine bessere Lösung als dynamic_cast?

Ich habe zunächst eine Klasse ein Fenster oder eine Ansicht darzustellen, die ich Ansicht genannt:

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

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

Das Problem ist jetzt, dass auf Android gibt es für Ansichten kein Titel ist, während unter Windows gibt es so habe ich beschlossen, erstellen eine andere Klasse:

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

Und dann implementieren schließlich die Klassen:

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

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

Dann muss ich Code machen, der den Namen für eine Ansicht nur dann setzt, wenn es möglich ist (wenn er von der Klasse NameableView erbt).

Also, wie kann ich dieses Problem lösen? Ich dachte zuerst über dynamic_cast, aber ich höre oft, dass zu viel dynamic_cast ein Hinweis auf ein Designproblem ist. Ich bin ein Anfänger in C++, vielleicht habe ich nicht den richtigen Weg gefunden und ich sollte das ganze Design ändern.

+0

Machen 'setName' eine implementierte no-op-Funktion in' View'? Es ist nicht so sehr eine Abstraktion, sie dort zu haben. – StoryTeller

+1

* "Ich versuche, plattformunabhängigen Code zu erstellen, damit ich OOP verwende." * - Das ist eine schlechte Idee, um damit anzufangen. Der Punkt von OOP, d. H. Von ** virtuellen Funktionen **, besteht darin, dass Sie die Implementierung von etwas auswählen und ändern können, während die Anwendung ausgeführt wird. –

+1

Es ist auch eine fehlerhafte Idee, ein abstraktes "Basiskonzept" für extrem unterschiedliche GUI-Umgebungen zu entwerfen.Ein besserer Entwurf besteht darin, die GUIs unabhängig voneinander zu entwickeln, wobei jede ihren eigenen Systemanforderungen entspricht, und sie gegebenenfalls eine gemeinsame Geschäftslogikkomponente oder ein Backend verwenden zu lassen. –

Antwort

3

Ich versuche plattformunabhängigen Code zu machen, also verwende ich OOP.

Dies ist kein optimaler Ansatz - polymorphe Hierarchien und virtual Funktionen erlauben verschiedene konkrete Objekttypen, die von der gleichen Schnittstelle erben anders zur Laufzeit, zu verhalten, aber sie wissen, dass die Plattform, die Sie zielen werden zur Kompilierungszeit.

Was Sie stattdessen tun sollten, ist statischen Polymorphismus und CRTP verwenden, um eine gemeinsame Schnittstelle, die jede konkrete pro-Plattform-Implementierung erfüllen müssen.

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(); 
    } 
}; 

Im Falle setName, sollten Sie eine supportsSetView Prüfung auf jeder Plattform bereitzustellen, die genannt werden können true zur Compile-Zeit, wenn die Ansicht zurückgibt. Dann führen Sie diese Überprüfung auf der Seite des Aufrufers durch und rufen nur setName auf, wenn die Prüfung erfolgreich ist.

Beispiel Nutzung:

#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 Seite:

MyView currentView; 

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

Als if constexpr(...) ‚s Auswertung zur Compile-Zeit auftritt, wird der Code nur setName nennen, wenn sie von MyView unterstützt wird.

Verwandte Themen