Абстрактный класс vs интерфейс в C++ [дубликат]


Возможные Дубликаты:
как вы объявляете интерфейс в C++?

это общий вопрос о C++. Как вы знаете, нет четкого различия между interface и abstract class в C++, в отличие от Java и C#. Когда было бы более предпочтительно использовать interface вместо abstract class в C++? Не могли бы вы привести несколько примеров?

5 78

5 ответов:

Я предполагаю, что с интерфейс вы имеете в виду класс C++ только с чисто виртуальные методы (т. е. без какого-либо кода), а не с абстрактный класс вы имеете в виду класс C++ с виртуальными методами, которые могут быть переопределены, и некоторый код, но по крайней мере один чистый виртуальный метод что делает класс не экземплярная. например:

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-таблицы, т. е. указатели на набор указателей на функции). Это помогает определить ABI (двоичный интерфейс приложения), который позволяет, например, построить компонент COM В C++ и использовать его в Visual Basic, или построить компонент COM В C и использовать его в C++, или построить компонент COM с Visual C++ версии X и использовать его с Visual C++ версии Y. Другими словами, с интерфейсами у вас есть высокая развязка между код клиента и код сервера.

кроме того, когда вы хотите построить DLL с объектно-ориентированным интерфейсом C++ (вместо чистых DLL C), как описано в в этой статье, лучше экспортировать интерфейсы ("зрелый подход") вместо классов 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
};

interface были в первую очередь популярны Java.
Ниже приведены характер interface и его эквиваленты на C++:

  1. interface может содержать только абстрактные методы без тела; эквивалент C++ является чистым virtual методы, хотя они могут/не могут иметь тела
  2. interface может содержать только static final элементы данных; C++ эквивалент static const элементы данных, которые являются константы времени компиляции
  3. несколько interface может быть implement ed от Java class, этот объект необходим, потому что Java class может наследовать только 1 class; C++ поддерживает множественное наследование с помощью virtual ключевое слово при необходимости

из-за пункта 3 interface концепция никогда не была официально введена в C++. Еще можно иметь гибкость, чтобы сделать это.

кроме того, вы можете сослаться на Бьярне часто задаваемые вопросы на эту тему.

абстрактный класс будет использоваться, когда требуется некоторая общая реализация. Интерфейс был бы, если вы просто хотите указать контракт, что части программы должны соответствовать тоже. Реализуя интерфейс, вы гарантируете, что вы будете реализовывать определенные методы. Расширяя абстрактный класс, вы наследуете часть его реализации. Поэтому интерфейс - это просто абстрактный класс без реализованных методов (все они чисто виртуальные).

чистые виртуальные функции в основном используются для определения:

а) абстрактные классы

Это базовые классы, где вы должны наследовать от них, а затем реализовать чистые виртуальные функции.

б) интерфейсы

Это "пустые" классы, где все функции являются чисто виртуальными и, следовательно, вы должны получить, а затем реализовать все функции.

чистые виртуальные функции на самом деле функции, которые не имеют реализации в базовый класс и должны быть реализованы в производном классе.

пожалуйста, не помещайте элементы в интерфейс, хотя это правильно сформулировать. Пожалуйста, не "удалить" интерфейс.

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

Class ClassImpl : public IInterface 
{ 
    … 
} 

Int main() 
{ 

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