110

重複の可能性:
C++ でインターフェイスを宣言するにはどうすればよいですか?

これは C++ に関する一般的な質問です。ご存じのとおり、Java や C# とは異なり、C++ では とinterfaceの間に明確な区別はありません。C++で an の代わりに anabstract classを使用する方が望ましいのはいつですか? いくつか例を挙げていただけますか?interfaceabstract class

4

5 に答える 5

151

インターフェイスとは、純粋な仮想メソッドのみを持つ(つまり、コードのない) C++ クラスを意味し、代わりに抽象クラスとは、オーバーライド可能な仮想メソッドといくつかのコードを持つ C++ クラスを意味しますが、少なくとも 1 つの純粋仮想メソッドを意味します。これにより、クラスがインスタンス化できなくなります。例えば:

class MyInterface
{
public:
  // Empty virtual destructor for proper cleanup
  virtual ~MyInterface() {}

  virtual void Method1() = 0;
  virtual void Method2() = 0;
};


class MyAbstractClass
{
public:
  virtual ~MyAbstractClass();

  virtual void Method1();
  virtual void Method2();
  void Method3();

  virtual void Method4() = 0; // make MyAbstractClass not instantiable
};

Windows プログラミングでは、インターフェイスCOMの基本です。実際、COM コンポーネントはインターフェイス (つまりv-tablesへのポインター、つまり一連の関数ポインターへのポインター) のみをエクスポートします。これは、たとえば、C++ で COM コンポーネントをビルドして Visual Basic で使用する、または C で COM コンポーネントをビルドして C++ で使用する、または Visual C++ で COM コンポーネントをビルドすることを可能にするABI (アプリケーション バイナリ インターフェイス)を定義するのに役立ちます。バージョン X を使用し、Visual C++ バージョン Y で使用します。つまり、インターフェイスを使用すると、クライアント コードとサーバー コードの間の分離が大きくなります。

さらに、(純粋な C DLL ではなく) C++ オブジェクト指向インターフェイスを使用して DLL をビルドする場合は、この記事で説明されているように、C++ クラスではなくインターフェイスをエクスポートする(「成熟したアプローチ」) ことをお勧めします (これは基本的にはCOM にはありますが、COM インフラストラクチャの負担はありません)。

具体的な特定の動作を指定せずに、コンポーネントをプログラムできる一連のルールを定義したい場合は、インターフェイスを使用します。このインターフェイスを実装するクラスは、それ自体でいくつかの具体的な動作を提供します。

代わりに、デフォルトのインフラストラクチャ コードと動作を提供したい場合は抽象クラスを使用し、クライアント コードがこの抽象クラスから派生できるようにして、純粋な仮想メソッドをカスタム コードでオーバーライドし、この動作をカスタムコード。たとえば、OpenGL アプリケーションのインフラストラクチャを考えてみてください。OpenGL の初期化、ウィンドウ環境のセットアップなどを行う抽象クラスを定義できます。次に、このクラスから派生させて、レンダリング プロセスやユーザー入力の処理などのカスタム コードを実装できます。

// Abstract class for an OpenGL app.
// Creates rendering window, initializes OpenGL; 
// client code must derive from it 
// and implement rendering and user input.
class OpenGLApp
{
public:
  OpenGLApp();
  virtual ~OpenGLApp();
  ...

  // Run the app    
  void Run();


  // <---- This behavior must be implemented by the client ---->

  // Rendering
  virtual void Render() = 0;

  // Handle user input
  // (returns false to quit, true to continue looping)
  virtual bool HandleInput() = 0;

  // <--------------------------------------------------------->


private:
  //
  // Some infrastructure code
  //
  ... 
  void CreateRenderingWindow();
  void CreateOpenGLContext();
  void SwapBuffers();
};


class MyOpenGLDemo : public OpenGLApp
{
public:
  MyOpenGLDemo();
  virtual ~MyOpenGLDemo();

  // Rendering
  virtual void Render();  // implements rendering code

  // Handle user input
  virtual bool HandleInput(); // implements user input handling


  //  ... some other stuff
};
于 2012-10-12T08:50:09.733 に答える
35

interface主にJavaによって普及しました。
以下は、 の性質interfaceとそれに相当する C++ です。

  1. interface本体のない抽象メソッドのみを含めることができます。C++ に相当するものは純粋なvirtualメソッドですが、本体を持つことができる/できない
  2. interfacestatic finalデータ メンバーのみを含めることができます。C++ に相当するのはstatic const、コンパイル時の定数であるデータ メンバーです。
  3. Javaは複数のinterface値を使用できます。Javaは 1 つしか継承できない ため、この機能が必要です。 C++ は、必要に応じてキーワードを使用して、多重継承をすぐにサポートしますimplementclassclassclassvirtual

ポイント 3 のため、interface概念は C++ で正式に導入されることはありませんでした。それでも、それを行う柔軟性を持つことができます。

これに加えて、このトピックに関するBjarne のFAQを参照できます。

于 2012-10-12T08:24:42.173 に答える
15

抽象クラスは、共通の実装が必要な場合に使用されます。インターフェイスは、プログラムの一部も準拠しなければならない契約を指定したいだけの場合です。インターフェイスを実装することにより、特定のメソッドを実装することが保証されます。抽象クラスを拡張することにより、その実装の一部を継承しています。したがって、インターフェイスは、メソッドが実装されていない単なる抽象クラスです (すべて純粋仮想です)。

于 2012-10-12T08:11:18.803 に答える
5

Pure Virtual Functions は、主に以下を定義するために使用されます。

a) 抽象クラス

これらは、それらから派生させて純粋仮想関数を実装する必要がある基本クラスです。

b) インターフェース

これらは、すべての関数が純粋な仮想である「空の」クラスであるため、すべての関数を派生させてから実装する必要があります。

純粋仮想関数は、実際には基本クラスに実装がなく、派生クラスに実装する必要がある関数です。

于 2012-10-12T10:40:31.233 に答える
-1

メンバーをインターフェースに入れないでください。言い回しは正しいですが。インターフェイスを「削除」しないでください。

class IInterface() 
{ 
   Public: 
   Virtual ~IInterface(){}; 
   … 
} 

Class ClassImpl : public IInterface 
{ 
    … 
} 

Int main() 
{ 

  IInterface* pInterface = new ClassImpl(); 
  … 
  delete pInterface; // Wrong in OO Programming, correct in C++.
}
于 2012-10-12T09:26:38.593 に答える