2

Say I have created two classes: Tires, and Car.

So I have four files: Tires.cpp, Tires.h, Car.cpp, Car.h.

The Car constructor takes Tires as its parameter. But I am not sure how to modify Car.h to include Tires.h.

Here's what I've done so far (note: they are in separate files)

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;
}

Thanks

pandascope
  • 117
  • 2
  • 2
  • 10
  • yup, that looks fine. so what is your question? (your title doesn't make sense to me) – Nawaz Dec 21 '10 at 18:32
  • As an aside, please do not use `using namespace std;` or similar statements in a header file - you get all sorts of 'interesting' side effects from that when you're dealing with symbols that are defined in multiple namespaces. – Timo Geusch Dec 21 '10 at 18:37
  • So basically I have a Car class and Tires Class. Constructor of Car class takes an instance of Tires class. Here's what I did (see above code) and it doesn't compile. Hope this made sense. Thanks. – pandascope Dec 21 '10 at 18:37

5 Answers5

4

Your approach seems fine here.

One thing to keep in mind when headers include other headers is that you may find you need to include an include guard:

// 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

This prevents you from declaring "class Tire {" et al. multiple times, should Tires.h happen to be included twice.

Another is that this line in Car.h is not needed:

class Tires;

This may be useful if you want to have declarations of Tires* or Tires&, but to do what you did next:

class Car
{
private:
   Tires tires;

... requires Tires to be a "complete type", for its size to be known, etc. You're already covered by that by having #include "Tires.h" anyway.

Lastly, some consider it bad form to have a using statement inside a header as you have done. This kind of breaks namespaces by bringing in std as a global namespace for all files that use this header. Imagine if every header did this, and did so for multiple namespaces. Eventually this becomes the same as there being no such thing as namespaces, and collisions are more likely.

asveikau
  • 39,039
  • 2
  • 53
  • 68
  • I tried your method and it is partially working. It compiles if i get rid of "Tires tires" under "private" in Car class. Am I not able to declare an instance of Tires in Car header file? – pandascope Dec 21 '10 at 19:14
  • @pandascope It sounds like the declaration of Tires is not working. What exactly did you do? – asveikau Dec 21 '10 at 20:27
  • Note that names starting with two underscores or one underscore and capital letter are reserved for implementation. Introducing such user-defined names is undefined behavior by C++ standard. – Öö Tiib Dec 21 '10 at 21:10
1

One thing you need is "include guards" so that you don't get a bunch of compiler errors due to redefinition.

Put something like the following in each of you header files:

#ifndef TIRES_H
#define TIRES_H

// contents of the header file...

#endif

Of course, change the name used for the macro guard (TIRES_H) as appropriate for each file. The macro name needs to be unique - basing it on the header file name is usually good enough. Also, many (most?) compilers support a #pragma once preprocessed directive that prevents headers from being processed more than once, but I still generally use the standard include guards.

This allows headers to be included more than once, since the guards cause subsequent includes of the file to essentially skip the entire contents.

Almost all C/C++ headers should have include guards so users don't need to worry about whether or not a necessary header was already included (the exceptions are headers which need to redefine things differently when included at different times - this is a pretty rare technique). Include guards also enable you to have header files (like cars.h in your example) include the headers they need without regard to what else might also include the headers, so your headers can be self-contained and can be included in any order.

Michael Burr
  • 333,147
  • 50
  • 533
  • 760
0

You have already included Tires.h in Car.h. You also have a forward declaration of class Tires in Car.h. You should eliminate either the include or the forward declaration. As you don't handle Tires as reference or pointer and you thus need the "behavior" of class Tires, you should eliminate the forward declaration.

Flinsch
  • 4,296
  • 1
  • 20
  • 29
  • A forward declaration alone wouldn't work here, since the size of `Tire` would not be known if he declared one to be a member of `Car`. He would need to change to a pointer or a reference for just a forward declaration to work. – asveikau Dec 21 '10 at 18:35
  • Yes, that's the reason for my advice to eliminate the forward declaration and stay with the include. Thanks for your additional explanations. Maybe I didn't express it understandably. – Flinsch Dec 21 '10 at 18:39
  • I got rid of forward declaration in Car.h but now I am getting compile errors relating to using undefined class 'Tires' and 'Tires" : 'class" type redefinition – pandascope Dec 21 '10 at 18:51
0

You've basically already answered your own question except that your Car(Tires) constructor has yet to be declared in your Car interface.

But I'd actually not do it that way. Your constructor should be Car(Tires const&) so that you can simply use the forward declaration you've already got in Car.h and not include Tires.h until in Car.cpp. The rest of your code could stay the same, but I'd still make a further change and use initialization rather than assignment in the constructor:

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

Even further, I recommend not EVER using '_' as the first character in any name. There's no need to and too often people get confused about when it is OK and when it is not.

Edward Strange
  • 40,307
  • 7
  • 73
  • 125
  • Ah I forgot to put Tires as one of the parameters in the constructor. Thanks, but I am still getting compile error. – pandascope Dec 21 '10 at 18:43
0

From all files delete line containing "using namespace std;"

From Car.h delete line containing "class Tires;" as it's included from #include "Tires.h"

Now wrap all your header file in header guards.

Charles Beattie
  • 5,739
  • 1
  • 29
  • 32
  • I tried doing that but now I am getting 3 compile errors: Tires : class type redefinition Car::tires uses undefined class Tires tires uses undefined class Tires – pandascope Dec 21 '10 at 18:49