web-dev-qa-db-fra.com

Classe abstraite vs interface en C ++

Duplicate possible:
Comment déclarez-vous une interface en C++?

C'est une question générale à propos de C++. Comme vous le savez, il n'y a pas de distinction claire entre interface et abstract class en C++ contrairement à Java et C #. Quand serait-il préférable d'utiliser un interface au lieu d'un abstract class en C++? Pouvez-vous donner quelques exemples?

91
fatma.ekici

Je suppose qu'avec interface vous entendez une classe C++ avec seulement pure virtuel (c'est-à-dire sans code) ), au lieu de classe abstraite , vous voulez dire une classe C++ avec des méthodes virtuelles pouvant être remplacées, ainsi que du code, mais au moins une méthode virtuelle pure qui rend la classe non instanciable. par exemple.:

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

En programmation Windows, interfaces sont fondamentaux en COM. En fait, un composant COM n’exporte que les interfaces (c'est-à-dire les pointeurs vers v-tables , c'est-à-dire les pointeurs vers un ensemble de pointeurs de fonction). Cela aide à définir un ABI (interface binaire d'application) qui permet, par exemple, de construire un composant COM en C++ et l'utiliser dans Visual Basic, ou construire un composant COM en C et l'utiliser en C++, ou générer un composant COM avec Visual C++ version X et l'utiliser avec Visual C++ version Y. En d'autres termes, avec interfaces que vous avez un découplage élevé entre le code client et le code serveur.

De plus, lorsque vous souhaitez créer des DLL avec une interface C++ orientée objet (au lieu de DLL C pure), comme décrit dans cet article , il est préférable d'exporter interfaces ("l'approche mature") au lieu des classes C++ (c'est essentiellement ce que fait COM, mais sans la charge de l'infrastructure COM).

J'utiliserais un interface si je veux définir un ensemble de règles à l'aide desquelles un composant peut être programmé, sans spécifier de comportement particulier concret. Les classes qui implémentent cette interface fourniront elles-mêmes un comportement concret.

Au lieu de cela, j'utiliserais un classe abstraite lorsque je veux fournir des valeurs par défaut code d'infrastructure et un comportement, et permettre code client à dériver de cette classe abstraite, en surchargeant les méthodes virtuelles pures avec du code personnalisé, et complete ce comportement avec le code personnalisé. Pensez par exemple à une infrastructure pour une application OpenGL. Vous pouvez définir une classe abstraite qui initialise OpenGL, configure l'environnement de fenêtre, etc., puis vous pouvez dériver de cette classe et implémenter du code personnalisé, par exemple. le processus de rendu et le traitement des entrées de l'utilisateur:

// 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
};
132
Mr.C64

interface ont été principalement rendus populaires par Java.
Vous trouverez ci-dessous la nature de interface et ses équivalents en C++:

  1. interface ne peut contenir que des méthodes abstraites sans corps; L'équivalent C++ est pure virtual méthodes, bien qu'elles puissent ou non avoir un corps
  2. interface ne peut contenir que static final données membres; L'équivalent C++ est static const données membres qui sont des constantes de temps de compilation
  3. Plusieurs interface peuvent être implemented par un Java class, cette fonctionnalité est nécessaire car un Java class ne peut hériter que 1 class; C++ supporte immédiatement l'héritage multiple avec l'aide du mot clé virtual lorsque cela est nécessaire

En raison du point 3, le concept interface n'a jamais été officiellement introduit en C++. On peut quand même avoir la possibilité de le faire.

En plus de cela, vous pouvez vous référer à FAQ de Bjarne à ce sujet.

32
iammilind

Une classe abstraite serait utilisée lorsqu'une implémentation commune était requise. Une interface serait si vous voulez simplement spécifier un contrat que certaines parties du programme doivent également se conformer. En implémentant une interface, vous garantissez que vous allez implémenter certaines méthodes. En étendant une classe abstraite, vous héritez d'une partie de son implémentation. Par conséquent, une interface est juste une classe abstraite sans aucune méthode implémentée (toutes sont virtuelles).

15
Will

Les fonctions virtuelles pures servent principalement à définir:

a) classes abstraites

Ce sont des classes de base où vous devez en dériver puis implémenter les fonctions virtuelles pures.

b) interfaces

Ce sont des classes "vides" où toutes les fonctions sont virtuelles et donc vous devez dériver puis implémenter toutes les fonctions.

Les fonctions virtuelles pures sont en réalité des fonctions qui n'ont pas d'implémentation dans la classe de base et doivent être implémentées dans une classe dérivée.

3
user1740176

S'il vous plaît ne mettez pas les membres dans une interface; si c'est correct dans la formulation. S'il vous plaît ne pas "supprimer" une interface.

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

Class ClassImpl : public IInterface 
{ 
    … 
} 

Int main() 
{ 

  IInterface* pInterface = new ClassImpl(); 
  … 
  delete pInterface; // Wrong in OO Programming, correct in C++.
}
0
zhouchen