4

この構成を想定します

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


class APoliticallyCorrectImplementationOfFooRelatedThings : private InterfaceForFoo
{

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

さて、このようにインターフェースからプライベートに継承することには、何か有用なシナリオがあるのだろうかと思います。

4

5 に答える 5

6

ええと、ここのみんなは「ノー」と言います。私は「はい、それ理にかなっています」と言います。

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

継承を行うことは、クラスの外部からprivateのメンバーにアクセスできないことを意味するのではVirtualBaseなく、への参照を介してそれらのメンバーにアクセスできないことを意味するだけですConcrete。ただし、Concreteとその友達はのインスタンスをキャストできConcreteVirtualBaseその後、誰でもパブリックメンバーにアクセスできます。単に、

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
于 2011-07-10T18:16:35.367 に答える
2

問題は、基本クラスに純粋仮想メソッドしかないことが重要なのはなぜですか?

2つのことはほとんど無関係です。プライベートとは、クラスの実装の詳細であり、パブリックインターフェイスの一部ではないことを意味しますが、実装の詳細としてインターフェイスを実装することをお勧めします。クラスを作成し、インターフェイスの実装を必要とするライブラリを使用して機能を実装することを決定したとします。これは実装の詳細であり、インターフェイスに純粋仮想関数しかないという理由だけで継承を公開する必要はありません。

于 2011-07-10T21:09:42.123 に答える
1

オブジェクト指向の側面ではprivate、抽象のそのような継承のユースケースはありませんclass

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

したがって、個人的なコーディングの規律を維持するのに役立ちます。この例のメッセージは、継承はオブジェクト指向の目的だけを意味するのではないということです。継承を使用して、継承チェーン(Java finalなど)を停止することもできます。

于 2011-07-10T17:59:13.623 に答える
-1

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

なぜあなたがインターフェースから個人的に継承するのか、私にはわかりません。そのようなものは、インターフェースの目的を打ち破ります。

それがインターフェースではなく、クラスである場合、それは理にかなっています:

class A {
    virtual void foo() = 0;

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

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

    }
};
于 2011-07-10T17:52:44.797 に答える
-1

え?いいえ、それはまったく意味がありません。インターフェースを提供する理由は、他の人にそのインターフェースを介してクラスを使用させたいからです。あなたがそれを実装することを彼らが知らない場合、それはどのように機能しますか?

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

上記の例は、外部の世界がそれを認識していないため機能しません。そのため、インスタンスをインスタンス化してに割り当てることはDoesFooできFooableません。newFooable*

于 2011-07-10T17:56:24.760 に答える