Как включить самостоятельно созданный класс в заголовочный файл другого самостоятельно созданного класса? - PullRequest
2 голосов
/ 21 декабря 2010

Скажем, я создал два класса: Шины и Автомобиль.

Итак, у меня есть четыре файла: Tires.cpp, Tires.h, Car.cpp, Car.h.

Конструктор Car принимает Tyres в качестве параметра.Но я не уверен, как изменить Car.h для включения Tires.h.

Вот что я сделал до сих пор (примечание: они находятся в отдельных файлах)

Tires.h

#include <iostream>
using namespace std;

class Tires
{
private:
    int numTires;

public:
    Tires();
};

Tires.cpp

#include <iostream>
#include "Tires.h"
using namespace std;

Tires::Tires()
{
    numTires = 4;
}

Car.h

#include <iostream>
#include "Tires.h" 
using namespace std;

class Tires; // Tried taking out forward declaration but still didn't work

class Car
{
private:
    Tires tires;

public:
    Car(Tires);   // Edited. Thanks to Noah for pointing out.

};

Car.cpp

#include <iostream>
#include "Car.h"
#include "Tires.h"
using namespace std;

Car::Car(Tires _tires)
{
    tires = _tires;
}

Спасибо

Ответы [ 5 ]

4 голосов
/ 21 декабря 2010

Ваш подход в данном случае кажется вполне подходящим.

Следует помнить одну вещь, когда заголовки включают другие заголовки, - вам может потребоваться включить включающий охрану:

// At the start of Tires.h:
//

// Only delcare this stuff if this is the first time including Tires.h:
//
#ifndef __myproject_Tires_h__
#define __myproject_Tires_h__

class Tires
{
   // [snip]
};

// Close the #ifdef above...
//
#endif

Это не позволяет вам объявить "class Tire {" и др.несколько раз, если Tires.h окажется включенным дважды.

Другое - то, что эта строка в Car.h не нужна:

class Tires;

Это может быть полезно, если вы хотите иметьдекларации Tires* или Tires&, но чтобы сделать то, что вы сделали дальше:

class Car
{
private:
   Tires tires;

... требует, чтобы Tires был "полным типом", чтобы его размер был известен, и т. д.Вы уже покрыли это наличием #include "Tires.h" в любом случае.

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

1 голос
/ 21 декабря 2010

Одна вещь, которая вам нужна, это «включить охрану» , чтобы вы не получили кучу ошибок компилятора из-за переопределения.

Поместите что-то вроде следующего в каждый заголовокfiles:

#ifndef TIRES_H
#define TIRES_H

// contents of the header file...

#endif

Конечно, измените имя, используемое для защиты макросов (TIRES_H), в соответствии с каждым файлом.Имя макроса должно быть уникальным - обычно достаточно хорошего имени файла заголовка.Кроме того, многие (большинство?) Компиляторы поддерживают директиву #pragma once preprocessed, которая предотвращает обработку заголовков более одного раза, но я все еще обычно использую стандартную защиту include.

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

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

0 голосов
/ 21 декабря 2010

Из всех файлов удалите строку, содержащую "using namespace std;"

Из Car.h удалите строку, содержащую "class Tires;", так как она включена в #include "Tires.h"

Теперь оберните весь заголовокфайл в заголовке стражи.

0 голосов
/ 21 декабря 2010

Вы в основном уже ответили на свой вопрос, за исключением того, что ваш конструктор Car(Tires) еще не объявлен в вашем Car интерфейсе.

Но я бы на самом деле не сделал этого таким образом.Ваш конструктор должен быть Car(Tires const&), чтобы вы могли просто использовать предварительное объявление, которое вы уже получили в Car.h, и не включать Tires.h до тех пор, пока в Car.cpp.Остальная часть вашего кода может остаться прежней, но я все равно внесу дополнительные изменения и использую инициализацию, а не присваивание в конструкторе:

Car::Car(Tires const& _tires) : tires(_tires) {}

Более того, я никогда не рекомендую НИКОГДА использовать '_' какпервый символ в любом имени.Нет необходимости и слишком часто люди путаются, когда все в порядке, а когда нет.

0 голосов
/ 21 декабря 2010

Вы уже включили Tires.h в Car.h. У вас также есть предварительное объявление о классе шин в Car.h. Вы должны исключить включение или предварительную декларацию. Поскольку вы не обрабатываете шины как ссылку или указатель и, следовательно, вам необходимо «поведение» класса Tires, вам следует исключить предварительное объявление.

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