Верно ли, что заголовочные файлы в C ++ и реализации абстрактных классов / интерфейсов в Java - это одна и та же идея? - PullRequest
6 голосов
/ 17 августа 2011

Я немного знаком с C ++ и знаю, что почти для каждого заголовочного файла я должен создать исходный файл, чтобы идти с ним.

Теперь я смотрю на интерфейсы Java и их реализацию, и это выглядит так же. Сначала вы просто называете переменные и методы в одном классе, а затем определяете их в другом классе.

Являются ли эти вещи в C ++ и Java в основном одинаковыми или похожими?

Ответы [ 8 ]

21 голосов
/ 17 августа 2011

Java-интерфейсы и файлы заголовка / реализации C ++ - это разные понятия.

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

Функции в C ++ могут быть объявлены , просто написав имя функции и аргументы:

void PrintMessage(std::string text);

И они могут быть определены , написав также тело метода:

void PrintMessage(std::string text)
{
  cout << text;
}  

Вы можете определить функцию только один раз в модуле компиляции (это весь текст, который видит компилятор после того, как #includes были заменены текстом файла, который они включают). Но вы можете объявлять функцию много раз, если объявления одинаковы. Вы должны определить каждую функцию, которая вызывается один раз. Вот почему у вас есть файл .cpp для каждого файла .h. .Cpp определяет все функции, которые объявлены в файле .h. Файл .h включается во все файлы .cpp, которые используют функции, и включается один раз в файл .cpp, который определяет функции.

Java выясняет, где определения функций для вас, когда она компилирует проект так, как он просматривает все файлы в проекте. C ++ компилирует только один файл .cpp за раз и просматривает только #include заголовочные файлы.

Интерфейс Java эквивалентен абстрактному базовому классу C ++. По сути, это объявление набора методов, включая типы аргументов, которые они принимают, и тип их возвращаемых значений. Интерфейс Java или абстрактный базовый класс C ++ могут наследоваться классом Java или классом C ++, который фактически определяет (реализует), что представляют собой эти методы.

В C ++, когда вы создаете класс, вы обычно (есть исключения) помещаете объявления методов в заголовочный файл, а определения помещаете в файл .cpp. Но в Java вам нужно только написать определения методов, эти определения эквивалентны определению и объявлению C ++ в одном. Вы можете поместить все определения метода java в один файл.

5 голосов
/ 17 августа 2011

Нет. Java interface - это абстрактный класс C ++. Учтите это:

// Java
interface Entity {
  void func();
}

class EntityImpl implements Entity {
  public void func() {
    System.out.println("func()");
  }
}

против

// C++
struct Entity {
  virtual void func() = 0;
  virtual ~Entity() {}

// just to emphasize it's a BASE class
protected: Entity() {} // not required
};

struct EntityImpl : Entity {
  void func() {
    std::cout << "func()" << std::endl;
  }
};
2 голосов
/ 17 августа 2011

Не совсем.

Во-первых, интерфейс Java не может содержать переменные, только константы и методы.

Во-вторых, интерфейсы Java должны создаваться только там, где это необходимо, т. Е. Там, где у вас есть API, которыйреализовано несколько классов, и вы хотите иметь возможность писать код, который обрабатывает их единообразно.Большинство классов Java должны , а не иметь соответствующий интерфейс, а большинство интерфейсов Java должны иметь два или более реализующих класса.

2 голосов
/ 17 августа 2011

Они очень разные.

Интерфейс Java больше похож на чистый абстрактный класс в C ++, где ни один из методов не имеет реализации.Они служат контрактом с объектом, гарантирующим возможность вызова методов.

Основная причина, по которой существуют интерфейсы, заключается в том, что Java не имеет множественного наследования , то есть класс может только продлить один супер класс.Класс может реализовывать несколько интерфейсов, поэтому вы можете определить любое количество операций, которые вы можете выполнить над классом через любое количество интерфейсов.

2 голосов
/ 17 августа 2011

Нет, они совершенно разные.

Java не имеет эквивалента «заголовочному файлу»: разделение декларации API / структур данных и реализации ваших классов просто не существует. Если вы хотите сослаться на некоторые сторонние классы, вам понадобятся файлы .class, которые точно такие же, что и вам, когда вы хотите запустить сторонние классы (обратите внимание, что они обычно хранятся в .jar файлах, но это только для удобства).

И самое близкое, что есть у C ++ к интерфейсам Java, - это чисто виртуальные классы: классы, которые определяют набор методов, но не определяют для них реализации. Как и в Java, вам нужно будет создать некоторые подклассы, чтобы они были действительно полезными, и эти подклассы обеспечат реализацию.

2 голосов
/ 17 августа 2011

NO, интерфейс - это конструкция, которая даже существует в c ++ как абстрактные классы. Это не имеет никакого отношения к разделению в файлах .hpp и .cpp. Интерфейс определяет некоторый набор функций, которые затем могут быть переопределены дочерними классами / реализацией

0 голосов
/ 17 августа 2011

C ++ старый и построен на C, который еще старше.В C ++ класс действительно представляет собой стиль C * struct с указателем на виртуальную таблицу, содержащий указатели на начальный адрес каждой функции в классе.

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

Компилятор C ++ будет обрабатывать каждый файл независимо, расширяя все макросы #include, чтобы включить их определения в каждый файл .cpp.Он также преобразует все вызовы функций в нотацию vtable, то есть

someInstance-> someMethod () становится (someInstance-> VTABLE [0]), предполагая, что someMethod () является первым объявленным в определенииclass someIntance.

Затем компилятор создает объектные файлы (так называемые единицы перевода) и размещает результирующий код обработки всех функций, реализованных во всех файлах .cpp, в макете памяти с таблицами перемещения для всех указателей ввсе vtables.Позднее компоновщик заменяет, разрешает символы в таблице перемещений в фактический адрес памяти функций.

Короче говоря, C ++ выглядит так, как он это делает для устаревших целей (и тот факт, что C не является объектно-ориентированным),Java является объектно-ориентированной с самого начала, то есть интерфейсы - это то, что вы МОЖЕТЕ использовать, в отличие от C ++, где определения классов - это то, что вы ДОЛЖНЫ иметь (struct и vtable, помните), и то, что вы ДОЛЖНЫ включать, так или иначе, в каждыйФайл .cpp, в котором вы хотите использовать этот класс.

0 голосов
/ 17 августа 2011

Никакой заголовочный файл в основном не содержит кода, который мы можем где-то повторно использовать, например, где интерфейс - это просто контракт, как все должно быть реализовано это не то же самое

...