Я разработчик JAVA, который пытается изучить C ++, но я действительно не знаю, как лучше всего использовать стандартные объявления функций.
В классе:
class Clazz
{
public:
void Fun1()
{
//do something
}
}
Или снаружи:
class Clazz
{
public:
void Fun1();
}
Clazz::Fun1(){
// Do something
}
Такое ощущение, что второй может быть менее читабельным ...
.cpp
файле.inline
.inline
ослабляет только одно правило определения, которое необходимо, если используется другая единица переводаClazz
Ответы:
C ++ является объектно-ориентированным в том смысле, что он поддерживает объектно-ориентированную парадигму разработки программного обеспечения.
Однако, в отличие от Java, C ++ не заставляет вас группировать определения функций в классы: стандартный способ объявления функции C ++ - просто объявить функцию без какого-либо класса.
Если вместо этого вы говорите об объявлении / определении метода, то стандартный способ состоит в том, чтобы поместить только объявление во включаемый файл (обычно с именем
.h
или.hpp
) и определение в отдельный файл реализации (обычно с именем.cpp
или.cxx
). Я согласен, что это действительно несколько раздражает и требует некоторого дублирования, но так был разработан язык.Для быстрых экспериментов и проектов с одним файлом подойдет все, что угодно ... но для больших проектов такое разделение практически необходимо.
Примечание: даже если вы знаете Java, C ++ - это совершенно другой язык ... и это язык, который нельзя изучить путем экспериментов. Причина в том, что это довольно сложный язык с множеством асимметрий и явно нелогичным выбором, и, что наиболее важно, когда вы делаете ошибку, нет «ангелов ошибок времени выполнения», которые спасут вас, как в Java ... но вместо этого есть » демоны неопределенного поведения ".
Единственный разумный способ изучить C ++ - это прочитать ... независимо от того, насколько вы умны, вы не сможете угадать, что решил комитет (на самом деле умение иногда даже является проблемой, потому что правильный ответ нелогичен и является следствием исторического наследие.)
Просто выберите одну или две хорошие книги и прочитайте их от корки до корки.
источник
Первый определяет вашу функцию-член как встроенную функцию , а второй - нет. Определение функции в этом случае находится в самом заголовке.
Вторая реализация поместит определение функции в файл cpp.
Оба семантически различны, и дело не только в стиле.
источник
Определение функции лучше вне класса. Таким образом, ваш код может оставаться в безопасности, если потребуется. Заголовочный файл должен содержать только объявления.
Предположим, кто-то хочет использовать ваш код, вы можете просто дать ему файл .h и файл .obj (полученный после компиляции) вашего класса. Для использования вашего кода ему не нужен файл .cpp.
Таким образом, ваша реализация никому не будет видна.
источник
Метод «Внутри класса» (I) действует так же, как метод «вне класса» (O).
Однако (I) можно использовать, когда класс используется только в одном файле (внутри файла .cpp). (O) используется, когда он находится в файле заголовка. cpp файлы всегда компилируются. Заголовочные файлы компилируются, когда вы используете #include "header.h".
Если вы используете (I) в файле заголовка, функция (Fun1) будет объявляться каждый раз, когда вы включаете #include "header.h". Это может привести к многократному объявлению одной и той же функции. Это сложнее скомпилировать и даже может привести к ошибкам.
Пример правильного использования:
File1: "Clazz.h"
//This file sets up the class with a prototype body. class Clazz { public: void Fun1();//This is a Fun1 Prototype. };
File2: "Clazz.cpp"
#include "Clazz.h" //this file gives Fun1() (prototyped in the header) a body once. void Clazz::Fun1() { //Do stuff... }
File3: "UseClazz.cpp"
#include "Clazz.h" //This file uses Fun1() but does not care where Fun1 was given a body. class MyClazz; MyClazz.Fun1();//This does Fun1, as prototyped in the header.
File4: "ТакжеUseClazz.cpp"
#include "Clazz.h" //This file uses Fun1() but does not care where Fun1 was given a body. class MyClazz2; MyClazz2.Fun1();//This does Fun1, as prototyped in the header.
File5: "DoNotUseClazzHeader.cpp"
//here we do not include Clazz.h. So this is another scope. class Clazz { public: void Fun1() { //Do something else... } }; class MyClazz; //this is a totally different thing. MyClazz.Fun1(); //this does something else.
источник
Clazz MyClazz
иClazz MyClazz2
?Функции-члены могут быть определены в определении класса или отдельно с помощью оператора разрешения области видимости ::. Определение функции-члена в определении класса объявляет функцию встроенной, даже если вы не используете встроенный спецификатор. Итак, вы можете определить функцию Volume (), как показано ниже:
class Box { public: double length; double breadth; double height; double getVolume(void) { return length * breadth * height; } };
Если хотите, можете определить ту же функцию вне класса, используя оператор разрешения области видимости :: следующим образом
double Box::getVolume(void) { return length * breadth * height; }
Здесь важно только то, что вам придется использовать имя класса непосредственно перед оператором ::. Функция-член будет вызываться с использованием оператора точки (.) На объекте, где она будет управлять данными, связанными с этим объектом, только следующим образом:
(с: http://www.tutorialspoint.com/cplusplus/cpp_class_member_functions.htm ), оба способа разрешены.
Я не эксперт, но думаю, что если вы поместите только одно определение класса в один файл, то это не имеет особого значения.
но если вы примените что-то вроде внутреннего класса или у вас есть определение нескольких классов, второе будет трудно читать и поддерживать.
источник
Первый должен быть помещен в файл заголовка (где находится объявление класса). Второй может быть где угодно, либо в заголовке, либо, как правило, в исходном файле. На практике вы можете поместить небольшие функции в объявление класса (которое объявляет их неявно встроенными, хотя в конечном итоге компилятор решает, будут ли они встроены или нет). Однако у большинства функций есть объявление в заголовке и реализация в файле cpp, как во втором примере. И нет, я не вижу причин, по которым это было бы менее читабельно. Не говоря уже о том, что вы можете разделить реализацию типа на несколько файлов cpp.
источник
Функция, которая определена внутри класса, по умолчанию рассматривается как встроенная функция. Простая причина, по которой вы должны определять свою функцию снаружи:
Конструктор класса проверяет виртуальные функции и инициализирует виртуальный указатель, чтобы указать на соответствующий VTABLE или таблицу виртуальных методов , вызывает конструктор базового класса и инициализирует переменные текущего класса, поэтому он фактически выполняет некоторую работу.
Встроенные функции используются, когда функции не такие сложные и позволяют избежать накладных расходов на вызов функции. (Накладные расходы включают переход и переход на аппаратном уровне.) И, как описано выше, конструктор не так просто рассматривать как встроенный.
источник
Встроенные функции (функции, которые вы объявляете в классе) каждый раз при их вызове вставляются в ваш основной код памяти. В то время как, когда вы объявляете функцию вне класса, когда вы вызываете функцию, она поступает из той же памяти. Вот почему это намного лучше.
источник