2016-05-15 6 views
2

Ich habe eine knifflige zirkuläre Einschluss Problem, dass ich nicht weiß, wie zu lösen. Fazit:Templated Funktion führt zu Circular Inclusion

IApp erbt von Component
Component implementiert eine Templat-Funktion in seinem Header-Datei, die IApp::registerForEvent

Welche Technik oder Methode verwendet, kann ich zu beheben verwenden/vermeiden diese kreisförmige Aufnahme?

class Component; 
class IApp; 

class Component 
{ 
    IApp* app; 

    // Error: Invalid use of incomplete type 'class IApp' 
    template<typename T> 
    void registerEvent(const int& evtId, Status (T::*func) (int)) 
    { 
     auto res = std::bind(func, (T*)this, std::placeholders::_1); 
     app->registerForEvent(evtId); 
    } 
}; 

class IApp : public Component 
{ 
public: 
    void registerForEvent(const int& evtId) 
    { 
     printf("IApp::registerForEvent\n"); 

     // ... 
    } 
}; 
+0

Sie können kompilieren, wenn Sie eine Forward-Deklaration verwenden, aber Sie beheben das Problem, indem Sie fragen: "Ist' IApp' wirklich eine 'Component'?" "Kann ich' IApp' in zwei Klassen zerlegen: eine 'Component' und eine' ComponentRegistry', vielleicht? " (https://www.youtube.com/watch?v=_LEomvWXOiI) –

+0

Ich vermute, dass "IApp" sowohl eine Schnittstelle und ein Singleton ist. Ich würde es sehr empfehlen, das zu überdenken. Du erhältst keine Stilpunkte, um mehr Muster zu verwenden als der nächste ("Eines Tages ging ich zu einem Brown Bag Lunch, und ein leitender Architekt verkündete stolz, dass er jedes GoF Design Pattern in einem Projekt verwendet hatte. Was er nicht erwähnte war, dass die Software nicht den Erwartungen der Kunden entsprach. Es hat nicht funktioniert. "http://baus.net/doersandtalkers; siehe auch https://code.google.com/archive/p/google-singleton -detektor/wikis/FAQ.wiki) –

Antwort

8

Definieren Sie registerEvent nach IApp.

class IApp; 

class Component 
{ 
    IApp* app; 
    template<typename T> 
    void registerEvent(const int& evtId, Status (T::*func) (int)); 
}; 


class IApp : public Component { 
    ... 
}; 

template <typename T> 
Component::registerEvent(const int& evtId, Status (T::*func) (int)) { 
    auto res = std::bind(func, (T*)this, std::placeholders::_1); 
    app->registerForEvent(evtId); 
} 

Falls erforderlich, definieren auch A::registerEvent nach Component::registerEvent.

4

Sie versuchen, eine abgeleitete Klasse in ihrer Basisklasse zu verwenden, die für mich nicht wie ein guter Designansatz aussieht. Ich würde vorschlagen, es in eine andere Klasse zu verschieben, auf die beide Klassen Zugriff haben.

2

Sie aggregieren ein abgeleitetes Klassenobjekt. Sie können damit die kreisförmige Abhängigkeit mit dem seltsam wiederkehrenden Vorlagenmuster lösen?

template <typename Aggregated> 
class Component 
{ 
    Aggregated* app; 

    template<typename T> 
    void registerEvent(const int& evtId, Status (T::*func) (int)) 
    { 
     auto res = std::bind(func, (T*)this, std::placeholders::_1); 
     app->registerForEvent(evtId); 
    } 
}; 

class IApp : public Component<IApp> 
{ 
public: 
    void registerForEvent(const int& evtId) 
    { 
     printf("IApp::registerForEvent\n"); 

     // ... 
    } 
}; 

Noch ist es mir nicht klar, was Sie versuchen zu tun. Zum einen nehmen Sie an, dass die übergebene Funktion Component :: registerEvent ein Mitglied von Component ist (Sie binden an (T *) dies), während Sie die Event-ID an die aggregierte IApp delegieren. Für mich scheint es, dass das Umdenken Ihr Design auch das Problem der zirkulären Abhängigkeit lösen könnte.