Заголовки C ++, связанные с классами - PullRequest
3 голосов
/ 26 декабря 2011

Я читал разные статьи и учебники по файлам заголовков.Я понимаю, что заголовки служат для удержания «интерфейса» от реализации.(и другие вещи, такие как оптимизация компиляции)

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

Когда я смотрю видеоурок, люди просто определяют функции своим телом в файле заголовка.Тогда другая статья определяет только функции (я думаю, это идея интерфейса).

Пока что я делаю простой класс с именем Color.реализация:

/* 
* File:   Color.cpp
* Author: Sidar
* 
* Created on 26 december 2011, 16:02
*/

#include <stdio.h>

#include "Color.h"

Color::Color() {

 reset();
}

Color::Color(const Color& orig) {

 a = orig.a;
 r = orig.r;
 g = orig.g;
 b = orig.b;
}

void Color::reset()
{
    a = 0;
    r = 0;
    g = 0;
    b = 0;
}

 Color::Color(unsigned int r, unsigned int g, unsigned int b, unsigned int a)
 {
   this->r = r;
   this->g = g;
   this->b = b;
   this->a = a;
 }

Color::~Color() {
   r = 0;
   g = 0;
   b = 0;
 }

 //getters____________________________
 unsigned int Color::getRed() const
 {
   return r;
 }

 unsigned int Color::getBlue() const
 {
   return b;
 }

 unsigned int Color::getGreen() const
 {
    return g;
 }

 unsigned int Color::getAlpha() const
 {
   return a;
 }

 //setters____________________________

 void Color::setRed(unsigned int r)
 {
   if(r > 255)r = 255;
   if(r < 0)r = 0;

   this->r = r;
}


void Color::setGreen(unsigned int g)
{
  if(g > 255)g = 255;
  if(g < 0)g = 0;

  this->g = g;
}

 void Color::setBlue(unsigned int b)
{
   if(b > 255)b = 255;
  if(b < 0)b = 0;

  this->b = b;
}

void Color::setAlpha(unsigned int a)
{
 if(a > 255)a = 255;
 if(a < 0)a = 0;

 this->a = a;
 }

 unsigned int Color::color()
 {
   return (int)a << 24 | (int)r << 16 | (int)g << 8 | (int)b << 0;
  }

и здесь заголовок

/* 
 * File:   Color.h
 * Author: Sidar
 *
 * Created on 26 december 2011, 16:02
 */

 #ifndef COLOR_H
#define COLOR_H
#include <string>

class Color {
public:

    Color();
    Color(const Color& orig);
    Color(unsigned int r,unsigned int g,unsigned int b, unsigned int a);

    virtual ~Color();
    //____________________
    void setRed(unsigned int r);
    unsigned int getRed()const;
    //____________________  
    void setBlue(unsigned int b);
    unsigned int getBlue()const;
    //____________________
    void setGreen(unsigned int g);
    unsigned int getGreen()const;
    //____________________
    void setAlpha(unsigned int a);
    unsigned int getAlpha()const;
    //____________________
    unsigned int color();

   void reset();

private:

    unsigned int r;
    unsigned int b;
    unsigned int g;
    unsigned int a;


};

#endif  /* COLOR_H */

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

Ответы [ 4 ]

4 голосов
/ 26 декабря 2011

Вы «не всегда» ничего не делаете, все зависит от обстоятельств, ваших целей и стандартов кодирования вашей группы или организации.

C ++ - очень гибкий язык, который позволяет вещам бытьсделано и организовано разными способами.

Некоторые причины могут быть использованы отдельные файлы реализации:

  1. Чтобы отделить реализацию от интерфейса, как вы предлагаете

  2. Чтобы ускорить время компиляции

  3. Для обработки циклических зависимостей

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

Некоторые причины, по которым вам могут не потребоваться отдельные файлы реализации:

  1. Вы используете шаблоны, которые"обычно" должно быть определено с помощью объявлений

  2. Вы НЕ хотите, чтобы реализация была отделена от интерфейса.Во многих случаях это облегчает понимание, поскольку вам не нужно переключаться между заголовком и файлом реализации.Это может быть контрпродуктивно, если вы имеете дело с большими классами со многими методами.

  3. Вы хотите, чтобы компилятор вставлял как можно больше кода.

  4. Вы создаете библиотеку кодов, для которой вы не хотите, чтобы пользователь беспокоился о сборке.Большинство библиотек Boost работают таким образом, когда вам не нужно использовать систему сборки Boost, что может быть довольно непростой задачей, но вместо этого вы просто включаете файлы заголовков в свой код, и это все, что вам нужно сделать, чтобы использоватьих.


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

Следует также отметить, что вы этого не делаетеобязательно использовать заголовочные файлы вообще.Вы можете определить некоторые классы прямо в ваших .cpp файлах.Это часто делается для закрытых классов, которые никогда не будут использоваться вне этого файла .cpp.

0 голосов
/ 26 декабря 2011

Если вы поместите реализации методов в заголовочный файл, компилятор C ++ может захотеть встроить код в call-сайты. Так что это может быть более эффективным.

Если у вас полностью определен класс в заголовочном файле, то вам не нужен файл .cpp, который немного упрощает понимание (если реализация короткая).

0 голосов
/ 26 декабря 2011

Заголовочные файлы не используются для «отделения интерфейса» от реализации, они уже содержат много деталей реализации, если вы не используете идиому pimpl.Это другая тема, и это может быть сделано на любом языке, который не имеет файла заголовка, такого как C # и Java.

Их реальное использование связано с тем фактом, что когда компилятор должен выделить место для экземпляракласса, он должен знать его размер.Чтобы вычислить размер, ему нужно полное объявление для этого класса.Поскольку вы, вероятно, собираетесь использовать экземпляр этого класса среди многих модулей перевода, единственный разумный способ обеспечить это объявление - поместить его в заголовочный файл и #include его при необходимости.

Когда вы создаете указатель на экземпляр (или ссылку), компилятору не нужно знать размер этого класса, поскольку указатель обычно имеет одинаковый размер 4 или 8 байт.В этих случаях вы можете просто использовать предварительную декларацию вместо #include заголовок.

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

0 голосов
/ 26 декабря 2011

Хорошо, прежде всего вот ответ, почему шаблоны могут быть реализованы только в заголовочных файлах:

Почему шаблоны могут быть реализованы только в заголовочном файле?

Это не потому, что это универсально, а потому, что компиляторы на самом деле обрабатывают шаблоны.Если вы не получили объяснения, отправьте мне сообщение:).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...