如何設置表明接口的類? 這只是一個抽象的基類嗎? html
若是您使用的是Microsoft的C ++編譯器,那麼您能夠執行如下操做: java
struct __declspec(novtable) IFoo { virtual void Bar() = 0; }; class Child : public IFoo { public: virtual void Bar() override { /* Do Something */ } }
我喜歡這種方法,由於它會致使更小的接口代碼,而且生成的代碼大小能夠顯着縮小。 使用novtable刪除對該類中vtable指針的全部引用,所以您永遠不能直接實例化它。 請參閱此處的文檔 - novtable 。 git
在C ++ 11中,您能夠輕鬆地徹底避免繼承: github
struct Interface { explicit Interface(SomeType& other) : foo([=](){ return other.my_foo(); }), bar([=](){ return other.my_bar(); }), /*...*/ {} explicit Interface(SomeOtherType& other) : foo([=](){ return other.some_foo(); }), bar([=](){ return other.some_bar(); }), /*...*/ {} // you can add more types here... // or use a generic constructor: template<class T> explicit Interface(T& other) : foo([=](){ return other.foo(); }), bar([=](){ return other.bar(); }), /*...*/ {} const std::function<void(std::string)> foo; const std::function<void(std::string)> bar; // ... };
在這種狀況下,接口具備引用語義,即您必須確保對象比接口更長(也可使接口具備值語義)。 算法
這些類型的接口有它們的優勢和缺點: 編程
最後,繼承是複雜軟件設計中全部邪惡的根源。 在Sean Parent的Value Semantics和基於概念的多態性中 (強烈推薦,此技術的更好版本在那裏解釋),研究瞭如下案例: 設計模式
假設我有一個應用程序,我使用MyShape
接口以多態方式處理個人形狀: ide
struct MyShape { virtual void my_draw() = 0; }; struct Circle : MyShape { void my_draw() { /* ... */ } }; // more shapes: e.g. triangle
在您的應用程序中,使用YourShape
界面對不一樣形狀執行相同操做: wordpress
struct YourShape { virtual void your_draw() = 0; }; struct Square : YourShape { void your_draw() { /* ... */ } }; /// some more shapes here...
如今說你想使用我在你的應用程序中開發的一些形狀。 從概念上講,咱們的形狀具備相同的界面,但爲了使個人形狀在您的應用程序中工做,您須要擴展個人形狀以下: 函數
struct Circle : MyShape, YourShape { void my_draw() { /*stays the same*/ }; void your_draw() { my_draw(); } };
首先,根本不可能修改個人形狀。 此外,多重繼承引領了意大利麪條代碼的道路(想象一下,第三個項目就是使用了TheirShape
界面......若是他們也調用了他們的繪圖函數my_draw
會發生什麼?)。
更新:有一些關於基於非繼承的多態性的新引用:
class Shape { public: // pure virtual function providing interface framework. virtual int getArea() = 0; void setWidth(int w) { width = w; } void setHeight(int h) { height = h; } protected: int width; int height; }; class Rectangle: public Shape { public: int getArea() { return (width * height); } }; class Triangle: public Shape { public: int getArea() { return (width * height)/2; } }; int main(void) { Rectangle Rect; Triangle Tri; Rect.setWidth(5); Rect.setHeight(7); cout << "Rectangle area: " << Rect.getArea() << endl; Tri.setWidth(5); Tri.setHeight(7); cout << "Triangle area: " << Tri.getArea() << endl; return 0; }
結果:矩形區域:35三角形區域:17
咱們已經看到抽象類如何根據getArea()定義接口,另外兩個類實現相同的函數,但使用不一樣的算法來計算特定於形狀的區域。
用純虛方法建立一個類。 經過建立覆蓋這些虛擬方法的另外一個類來使用該接口。
純虛方法是一種定義爲虛擬並分配給0的類方法。
class IDemo { public: virtual ~IDemo() {} virtual void OverrideMe() = 0; }; class Child : public IDemo { public: virtual void OverrideMe() { //do stuff } };
除了C#/ Java中的抽象基類以外,你有一個特殊的接口類型類的所有緣由是由於C#/ Java不支持多重繼承。
C ++支持多重繼承,所以不須要特殊類型。 沒有非抽象(純虛擬)方法的抽象基類在功能上等同於C#/ Java接口。