2011-07-10 6 views
4

はこのようにインターフェイスから個人継承した場合さて、私は思ったんだけど、これは抽象クラス(純粋仮想クラス)から個人的に継承するのは理にかなっていますか?

struct InterfaceForFoo 
{ 
    virtual void GetItDone() = 0; 
}; 


class APoliticallyCorrectImplementationOfFooRelatedThings : private InterfaceForFoo 
{ 

    public: 
    void GetItDone() { /*do the thing already*/ }; 
}; 

を構築したとは、任意の有用なシナリオを持っています。

答えて

5

ここで誰もが「いいえ」と言っています。私は "はい、それは意味する"と言う。継承privateを作る

class VirtualBase { 
public: 
    virtual void vmethod() = 0; 
    // If "global" is an instance of Concrete, then you can still access 
    // VirtualBase's public members, even though they're private members for Concrete 
    static VirtualBase *global; 
}; 

// This can also access all of VirtualBase's public members, 
// even if an instance of Concrete is passed in, 
void someComplicatedFunction(VirtualBase &obj, ...); 

class Concrete : private VirtualBase { 
private: 
    virtual void vmethod(); 
public: 
    void cmethod() { 
     // This assignment can only be done by Concrete or friends of Concrete 
     VirtualBase::global = this; 
     // This can also only be done by Concrete and friends 
     someComplicatedFunction(*this); 
    } 
}; 

あなたはクラスの外からVirtualBaseのメンバーにアクセスできないことを意味するものではありません、それはあなたがConcreteを参照することにより、これらのメンバーにアクセスできないことを意味します。しかし、Concreteとその友達はConcreteのインスタンスをVirtualBaseにキャストできます。誰でも公開メンバーにアクセスできます。単純に、

Concrete *obj = new Concrete; 
obj->vmethod(); // error, vmethod is private 

VirtualBase *obj = VirtualBase::global; 
obj->vmethod(); // OK, even if "obj" is really an instance of Concrete 
+0

私は「いいえ」と言っていません。私の答えを見てください。 :) – iammilind

-1

関数が必要な場合は、それを実装します。他のクラスでは使用できない関数を強制するのは意味がありません。

なぜ私はインターフェイスから私的に継承するのか分かりません。そのようなものはインタフェースの目的を破るものです。

それはインターフェースが、代わりにクラスでないなら、それは理にかなって:

class A { 
    virtual void foo() = 0; 

    void bar() { 
     foo(); 
    } 
}; 

class B : private A { 
    virtual void foo() { 

    } 
}; 
0

え?いいえ、それは全く意味がありません。なぜなら、インタフェースを提供する理由は、他の人がそのインタフェースを通してクラスを使用することを望むからです。。彼らはあなたがそれを実装することを知らない場合、それはどのように機能しますか?外の世界はDoesFooはあなたがすることができませんnewそのインスタンスなど、Fooableであることを知っているとFooable*に割り当てていないため

#include <vector> 

class Fooable{ 
public: 
    virtual void foo() = 0; 
}; 

class DoesFoo 
    : private Fooable 
{ 
    void foo(); 
}; 

int main(){ 
    std::vector<Fooable*> vf; 
    vf.push_back(new DoesFoo()); // nope, doesn't work 
    vf[0]->foo(); 
} 

上記の例では動作しません。

+0

私はこれまでに答えを得られるとは思わないが... ... @anonymous downvoter、説明を気にする? – Xeo

1

オブジェクト指向の側面では、classのようなそのようなprivate継承の使用例はありません。

しかし、あなたが子供のclassに特定の方法を派生させなければならないことを強制したい場合は、これを使用することができます。たとえば:

struct implement_size 
{ 
    virtual size_t size() = 0; 
}; 

class MyVector : private implement_size 
{ 
public: 
    size_t size() { ... } // mandatory to implement size() 
} 

class MyString : private implement_size 
{ 
public: 
    size_t size() { ... } // mandatory to implement size() 
}; 

だから、それだけで個人的なコーディング規律を維持するのに役立ちます。この例のメッセージは、継承はオブジェクト指向の目的だけではないということです。 use inheritance for stopping inheritance chain(Javaファイナルのようなもの)でもできます。

+0

「オブジェクト指向アスペクト」とは何ですか? – curiousguy

+0

@curiousguy、=> OO用語/哲学。 – iammilind

+0

純粋な仮想関数を使用してメソッドの実装を強制するだけでは不平を言います。 MyVectorとMyStringのどちらかがインタフェース( 'Container'?)を共有しているかどうかを示します。もしそうでなければ、偽のインターフェースを作ることに意味はなく、 'size()'をポリモーフィックに使うつもりがないときには仮想関数を作るのにはあまり意味がありません。 –

1

なぜ基本クラスには純粋な仮想メソッドしかないのですか?

2つの事柄はほとんど無関係です。プライベートは、それがパブリックインターフェイスの一部ではなくクラスの実装の詳細であることを意味しますが、インプリメンテーションの詳細としてインターフェイスを実装することもできます。クラスを作成し、インターフェイスを実装する必要があるライブラリを使用して機能を実装することを検討することを検討してください。実装の詳細は、のインタフェースが純粋な仮想関数しか持たないため、継承を公開する必要はありません。

関連する問題