2016-07-10 11 views
2

Ich versuche, ein Stück Code zu entwerfen, die die Verwendung eines Algorithmus erfordert. Der Algorithmus sollte in Zukunft leicht durch jemand anderes ersetzt werden können. Also in meinem LargeClass muss es eine Möglichkeit geben, einen bestimmten Algorithmus aufzurufen.Verwenden einer Interface-Klasse als Mitglied Typ in einer anderen Klasse

Ich habe einen Beispielcode unten zur Verfügung gestellt. Meine Idee war, eine Interface-Klasse IAlgorithm zu machen, so dass Sie selbst eine Implementierung bereitstellen müssen. Ich dachte, dass Sie es im Konstruktor der LargeClass zu welcher jemals abgeleiteten Klasse initialisieren konnten. Allerdings kompiliert der folgende Code in VS2015 nicht, weil IAlgorithm: cannot instantiate abstract class

Meine Frage: Wie soll ich das entwerfen, um das gewünschte Ergebnis zu erhalten?

Vielen Dank im Voraus!

Algorithm.h

class IAlgorithm 
{ 
protected: 
    virtual int Algorithm(int, int) = 0; 
}; 

class algo1 : public IAlgorithm 
{ 
public: 
    virtual int Algorithm(int, int); 
}; 

class algo2 : public IAlgorithm 
{ 
public: 
    virtual int Algorithm(int, int); 
}; 

Algorithm.cpp

#include "Algorithm.h" 

int algo1::Algorithm(const int a, const int b) 
{ 
    // Do something 
} 

int algo2::Algorithm(const int a, const int b) 
{ 
    // Do something 
} 

Source.cpp

#include "Algorithm.h" 

class LargeClass 
{ 

private: 
    IAlgorithm algo; 
}; 

int main() 
{ 


} 
+2

Verwenden eine Referenz oder einen Zeiger für das Element. –

+0

"Wie soll ich das gestalten, um das gewünschte Ergebnis zu erhalten?" - Die Frage ist, welches Ergebnis willst du wirklich? Ich meine, Sie haben sich entschieden, einen polymorphen Algorithmus zu verwenden, aber warum? Was ist das Endergebnis, nach dem wir suchen? Ich frage das, weil polymorphe Schnittstellen oft unflexibel sind und weitgehend zugunsten von Lambdas, Verschlüssen und Templates veraltet sind. –

+1

Sie haben nicht genug darüber nachgedacht, wie Sie die * spezifische * Implementierung der Schnittstelle erstellen und zerstören werden. Sie bitten den Compiler, es für Sie zu tun, und es beschwert sich richtig, dass es nicht weiß, wie das zu tun ist. Im Moment hat Ihr Code kein Orakel, das Ihnen die Antwort gibt. –

Antwort

4

Mein erster thoug Das würde heißen, warum sollte man solch eine primitive Schnittstelle benutzen?

OK, wir haben eine Anforderung, dass für einen Prozess ein Algorithmus benötigt wird. Dieser Algorithmus muss polymorph sein, zwei Ints haben und einen int zurückgeben.

Alles gut und gut. Dafür gibt es bereits ein Konstrukt in der Standardbibliothek. Es ist ein std::function anrufen. Dies ist ein Wrapper um jedes Funktionsobjekt mit einer kompatiblen Schnittstelle.

Beispiel:

#include <functional> 
#include <iostream> 

class LargeClass 
{ 
    public: 

    using algorithm_type = std::function<int(int,int)>; 

    LargeClass(algorithm_type algo) 
    : _algo(std::move(algo)) 
    {} 

    int apply(int x, int y) { 
    return _algo(x,y); 
    } 

private: 
    algorithm_type _algo; 
}; 

int test(LargeClass&& lc) { 
    return lc.apply(5,5); 
} 

int divide(int x, int y) { return x/y; } 

int main() 
{ 
    // use a lambda 
    std::cout << test(LargeClass{ [](auto x,auto y){ return x + y; } }); 

    // use a function object 
    std::cout << test(LargeClass{ std::plus<>() }); 

    // use a free function 
    std::cout << test(LargeClass{ divide }); 

    // use a function object 

    struct foo_type { 
    int operator()(int x, int y) const { 
     return x * 2 + y; 
    } 
    } foo; 
    std::cout << test(LargeClass{ foo_type() }); 
    std::cout << test(LargeClass{ foo }); 

} 
+0

Danke für die Bereitstellung einer so netten Antwort – DoubleTrouble