2012-03-06 2 views
90

Я смущен тем, как отделить код реализации и декларации простого класса от нового файла заголовка и cpp. Например, как я могу отделить код для следующего класса?Разделение кода класса на файл заголовка и cpp

class A2DD 
{ 
    private: 
    int gx; 
    int gy; 

    public: 
    A2DD(int x,int y) 
    { 
    gx = x; 
    gy = y; 
    } 

    int getSum() 
    { 
    return gx + gy; 
    } 
}; 
+6

Только несколько комментариев: Конструктор должен всегда использовать список инициализации вместо установки членов в теле. Для хорошего и простого объяснения см .: http://www.codeguru.com/forum/showthread.php?t=464084 Это также, по крайней мере, большинство мест, имеющих обыкновение публичное поле вверху. Это ничего не повлияет, но поскольку публичные поля являются документацией вашего класса, имеет смысл иметь это наверху. – martiert

+1

@martiert Наличие 'public:' членов наверху _could_ влияет на _lot_, если пользователь переместил их в соответствии с этим советом, - но имел порядок отношений между членами и еще не знал, что члены инициализируются в порядке их объявления; -) –

+1

@underscore_d это правда. Но опять же, мы все компилируем с предупреждениями как ошибки и все предупреждения, о которых мы можем думать, не так ли? Это, по крайней мере, скажет вам, что вы это испортили, но да, люди используют способы для небольших предупреждений и просто игнорируют их :( – martiert

ответ

138

Объявление класса входит в заголовочный файл. Важно, чтобы вы добавили защитные устройства #ifndef, или если вы находитесь на платформе MS, вы также можете использовать #pragma once. Также я опустил закрытый, по умолчанию члены класса C++ являются закрытыми.

// A2DD.h 
#ifndef A2DD_H 
#define A2DD_H 

class A2DD 
{ 
    int gx; 
    int gy; 

public: 
    A2DD(int x,int y); 
    int getSum(); 

}; 

#endif 

и реализация идет в файле CPP:

// A2DD.cpp 
#include "A2DD.h" 

A2DD::A2DD(int x,int y) 
{ 
    gx = x; 
    gy = y; 
} 

int A2DD::getSum() 
{ 
    return gx + gy; 
} 
+27

Помните, что если вы занимаетесь программированием шаблонов, вам нужно сохранить все в файле .h, чтобы компилятор создавал правильный код в момент компиляции. – linello

+0

im получение ошибки с дублирующимся символом im не уверен, как использовать его .ld: дублировать символ A2DD :: A2DD (int, int) в ./src/rstring.o и ./src/A2DD.o для архитектуры x86_64 – drdrdr

+1

у вас есть материал '# ifndef' в заголовке? – fritzone

5

В основном модифицированный синтаксис объявления функции/определений:

a2dd.h

class A2DD 
{ 
private: 
    int gx; 
    int gy; 

public: 
    A2DD(int x,int y); 

    int getSum(); 
}; 

a2dd.cpp

A2DD::A2DD(int x,int y) 
{ 
    gx = x; 
    gy = y; 
} 

int A2DD::getSum() 
{ 
    return gx + gy; 
} 
2

Выходите заявления в заголовочном файле:

class A2DD 
{ 
    private: 
    int gx; 
    int gy; 

    public: 
    A2DD(int x,int y); // leave the declarations here 
    int getSum(); 
}; 

И поместите определения в файл реализации.

A2DD::A2DD(int x,int y) // prefix the definitions with the class name 
{ 
    gx = x; 
    gy = y; 
} 

int A2DD::getSum() 
{ 
    return gx + gy; 
} 

Вы можете смешать два (оставить getSum() определение в заголовке, например). Это полезно, так как дает компилятору больше шансов на inlining, например. Но это также означает, что смена реализации (если она оставлена ​​в заголовке) может вызвать перестройку всех других файлов, содержащих заголовок.

Обратите внимание, что для шаблонов вам необходимо сохранить все в заголовках.

+1

Ввод частных членов и функций в файл заголовка не считается утечкой данных реализации? – Jason

+0

@ Джейсон, вроде. Это * необходимо * детали реализации. Например, я должен знать, сколько пространства класс будет потреблять в стеке. Реализации функций не нужны для других единиц компиляции. –

3

A2DD.h

class A2DD 
{ 
    private: 
    int gx; 
    int gy; 

    public: 
    A2DD(int x,int y); 

    int getSum(); 
}; 

A2DD.cpp

A2DD::A2DD(int x,int y) 
    { 
    gx = x; 
    gy = y; 
    } 

    int A2DD::getSum() 
    { 
    return gx + gy; 
    } 

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

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

1

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

Например:

class A { 
public: 
    A(); // only declaration in the .h unless only a short initialization list is used. 

    inline int GetA() const { 
    return a_; 
    } 

    void DoSomethingCoplex(); // only declaration 
    private: 
    int a_; 
}; 
9

В общем, ваш .h содержит класс defition, в котором все ваши данные и все ваши объявления методов.Как это в вашем случае:

A2DD.h: 

class A2DD 
{ 
    private: 
    int gx; 
    int gy; 

    public: 
    A2DD(int x,int y);  
    int getSum(); 
}; 

И тогда ваш .cpp содержит реализации методов, как это:

A2DD.cpp: 

A2DD::A2DD(int x,int y) 
{ 
    gx = x; 
    gy = y; 
} 

int A2DD::getSum() 
{ 
    return gx + gy; 
}