Подтвердить что ты не робот

Абстрактный класс vs Интерфейс в С++

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

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

4b9b3361

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

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

Ответ 2

interface были в основном популярны Java.
Ниже приведена природа interface и ее эквивалентов С++:

  • interface может содержать только абстрактные методы без тела; Эквивалент С++ - это чистые методы virtual, хотя они могут/не могут иметь тело
  • interface может содержать только элементы данных static final; С++ эквивалентный элемент данных static const, которые являются константы времени компиляции
  • Несколько interface могут быть implement ed с помощью Java class, это необходимо, потому что Java class может наследовать только 1 class; С++ поддерживает множественное наследование сразу с помощью virtual ключевое слово при необходимости

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

Кроме того, вы можете ссылаться на Bjarne FAQ на эту тему.

Ответ 3

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

Ответ 4

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

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

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

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

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

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

Ответ 5

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

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

Class ClassImpl : public IInterface 
{ 
    … 
} 

Int main() 
{ 

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