using two differenct classes

Pages: 12
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>

using namespace std;

#include "car.h"
#include "truck.h"

int main(){
	
	cout << "---------Program Initiated-----------" << endl << endl;
	
}//---------main() 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class car{
	
	public:
		
	string color;
	int length;
	int height;
	
	car(){
		
		color = "black";
		length = 6;
		height = 4;
		
	}//-----constructor()
	
	car(truck tobj){
		
		color = tobj.color;
		length = ((tobj.length) - ((40/100) * tobj.length));
		height = ((tobj.height) - ((40/100) * tobj.height));
		
	}//------------constructor(truck)
	
};


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class truck{
	
	public:
		
	string color;
	int length;
	int height;
	
	truck(){
		
		color = "black";
		length = 12;
		height = 8;
		
	}//-----constructor()
	
};


and compiler says (for car(truck tobj) constructor) :
17 12 car.h [Error] expected ')' before 'tobj'

I know truck.h is included latter so truck.h might not be visible in car.h so do I have to include truck.h before car.h too (I did this too like:

#include "car.h"
#include "truck.h"
#include "car.h"
#include "truck.h"

but that's an error)

how can I use type truck in car class and also type car in truck class
Since car.h uses truck, the include for truck.h must precede the include for car.h. Switch lines 5 and 6 in main.cpp.

how can I use type truck in car class and also type car in truck class

I see no reference to car in your truck class.

If you do indeed need to reference car in your truck class, you have what is called a circular dependency. The solution is to declare one as a forward.
 
class car;

Then inside truck, you can only reference car by pointer or reference (not by value).
http://stackoverflow.com/questions/625799/resolve-circular-dependencies-in-c

http://herbsutter.com/2013/08/19/gotw-7a-solution-minimizing-compile-time-dependencies-part-1/

You have implementations of the constructors within the definitions of the classes. That makes it harder to dodge dependencies. The class definition has to be in a header (with inclusion guards) so it can be included in multiple translation units, but the implementations should be in one source file.


PS. Use initializer list in constructor.
1
2
3
truck::truck()
: color("black"), length(12), height(8)
{}

Initializer list sets the values for members during their construction, while your constructors assign new values to already constructed members.

If you have C++11, then there is even more initialization syntax to benefit from.
after forward declaring compiler

Error: tobj has incomplete datatype

Warning: forward declaration of class truck


when you need to use both data types in each-other what is real proper syntax which won't give errors as well as warnings too
What do you have now, exactly?
> Since car.h uses truck, the include for truck.h must precede the include for car.h.
> Switch lines 5 and 6 in main.cpp.
.oi
put #include "truck.h" in car.h
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>

using namespace std;

#include "car.h"
#include "truck.h"

int main(){
	
	cout << "---------Program Initiated-----------" << endl << endl;
	
}//---------main() 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class truck;

class car{
	
	public:
		
	string color;
	int length;
	int height;
	
	car(){
		
		color = "black";
		length = 6;
		height = 4;
		
	}//-----constructor()
	
	car(truck tobj){
		
		color = tobj.color;
		length = ((tobj.length) - ((40/100) * tobj.length));
		height = ((tobj.height) - ((40/100) * tobj.height));
		
	}//------------constructor(truck)
	
};


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class car;

class truck{
	
	public:
		
	string color;
	int length;
	int height;
	
	truck(){
		
		color = "black";
		length = 12;
		height = 8;
		
	}//-----constructor()
	
};


tobj incomplete datatype error
ne555 I latter need to use car type in truck class too, I've gotta be the victim of circular dependency.
As far as I can tell, your most recent code post is exactly the same as your first code post with the exception of the two forward declarations. Other than that you're not paying attention to what has been suggested.

1) You did not switch the order of includes (or put #include "truck.h" in car.h as suggested by ne555).

2) You have not implemented include guards as suggested by keskiverto) to prevent including the same file multiple times.

3) As I explained in my earlier port, something declared forward can NOT be passed by value as you are doing in line 19 of car.h. Change that to pass truck by reference. Note: You could pass by value here IF you had changed the order of the includes as I suggested earlier.


I guess you are talking about #ifndef ---- #endif thing

since I started to work on this thing I have been seeing this type of things but I don't know how do these work also there has been something like

#ifndef file_h
#define file_h

#endif

but I wanna know does underscore represent period ??? Like file_h = file.h ???

and I got this that forward declaration doesn't allow pass by value but why??? what's the logic behind it?

I'm new and in learning phase so please don't get angry if I write some stupid
There is no special significance to the _ in an include guard. But, yes by convention an _ can be used to represent a . since . is not legal in a #define name. The point is the name being defined is unique to the file. i.e. We don't want to use #ifndef file_h in both car.h and truck.h.

The way include guards work is as follows:
1
2
3
4
5
6
7
// Some header file 
#ifndef somehdr_h  // If this file has been included before, then somehdr_h will be defined and everything up to the #endif will be skipped to prevent duplicate declarations.
// Everything within the ifndef will be included if this is the first inclusion
#define somehdr_h // Since this file has not been included before, we define some symbol that we can test to detect if the file has been included before.

//  Declarations that should only be included once
#endif // Ends conditional inclusion 


When something is passed by value, the compiler has to know how big it is (the object is pushed on the stack). When something is declared forward and the compiler has not seen the complete declaration yet, so the compiler does not yet know how big the object is. This is why you get an error such as "reference to incomplete type". i.e. The compiler knows the name exists, but not how bit it is.

Passing by reference or passing by pointer are okay, because the compiler only has to push a pointer onto the stack and the compiler knows how big pointers are.

Most of us are here to help beginners. However, there is an expectation that if you are given multiple suggestions on how to fix something that would follow at least some of the suggestions given.
rest of the code is same I just changed the constructor

1
2
3
4
5
car(truck * tobj){
		
		color = (* tobj).color;
		
	}//------------constructor(truck) 


now compiler says: invalid use of incomplete type 'class truck'
closed account (10X9216C)
This is where putting the body of the function into the header file fails.

Put the body into a source file, you allow yourself the ability to include the truck header, thus not making it an incomplete type, after the inclusion of the car header.

1
2
3
4
5
6
7
8
9
10
11
12
// car.cpp

#include "car.h"
#include "truck.h" // truck no longer an incomplete type


car::car(const truck& t)
    : color(t.color)
{
   // etc
}


Anyway, another solution would be to just have the truck and car derive from a similar class.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Transportation
{
    std::string color;
    int length;
    int width;
public:

    void SetTransport(const Transportation& t) { *this = t; } // or something like that

};

class Truck : public Transportation
{
};

class Car : public Transportation
{
};


Why you would want to copy that kind of information into a car from a truck, doesn't really make sense in term of objects.
I'm sorry guys I tried much of your suggestions and I'm unable to work on my example please if you guys you have any other example/tutorial on circular dependency in C++ then please suggest me, now I want step by step followup.

Please a good circular dependency tutorial/example/video please

And I really appreciate your previous help, thanks for that.
So you say that you had something like below and it did give an error? What error, exactly?
car.h
1
2
3
4
5
6
7
8
9
10
11
#ifndef CAR_H
#define CAR_H

struct truck;

struct car {
  int foo;

  car ( truck t );
};
#endif 

car.cpp
1
2
3
4
5
6
#include "car.h"
#include "truck.h"

car::car ( truck t )
 : foo( t.bar * 2 )
{}

truck.h
1
2
3
4
5
6
7
8
9
10
11
#ifndef TRUCK_H
#define TRUCK_H

struct car;

struct truck {
  int bar;
  truck();
  void gaz( car b );
};
#endif 

truck.cpp
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
#include "truck.h"
#include "car.h"

truck::truck()
 : bar(7)
{}

void truck::gaz ( car b )
{
  std::cout << b.foo << '\n';
}

main.cpp
1
2
3
4
5
6
7
8
9
#include "truck.h"
#include "car.h"

int main() {
  truck hello;
  car world( hello );
  hello.gaz( world );
  return 0;
}
You still haven't shown any code indicating that truck requires car.

myesolar showed you how to get rid of the reference to an incomplete type by moving car's constructor to car.cpp. This is the best solution.

Or as previously pointed out, you can include truck.h inside car.h.
car.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include "truck.h"
class car
{
public:
    string color;
    int length;
    int height;
	
    car()
    {   color = "black";
        length = 6;
        height = 4;
    } //-----constructor()
	
    car (truck & tobj)
   {    color = tobj.color;
        length = ((tobj.length) - ((40/100) * tobj.length));
        height = ((tobj.height) - ((40/100) * tobj.height));
    }//------------constructor(truck)	
};




closed account (10X9216C)
Article if you still need it: http://www.cplusplus.com/articles/Gw6AC542/
Well the last code which I tried and couldn't compile was

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//cartruck.cpp

#include <iostream>

using namespace std;

#include "truck.h"
#include "car.h"

int main(){
	
	cout << "---------Program Initiated-----------" << endl << endl;
	
	return 0;
	
}//---------main() 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//car.h

#ifndef car_h
#define car_h

class car{
	
	public:
		
	string type;
	string color;
	int length;
	int height;
	
	car();
	
	car(truck);
	
	void print();
	
};

#endif 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//car.cpp

#include "car.h"
#include "truck.cpp"

	car::car(){
		
		type = "car";
		color = "black";
		length = 6;
		height = 4;
		
	}//-----constructor()
	
	car::car(truck tobj){
		
		type = "car";		
		color = tobj.color;
		length = tobj.length;
		height = tobj.height;
		
	}//------------constructor(truck)
	
	void car::print(){
		
		cout << "type: " << type << "\tColor: " << color << "\tlength: " << length << "\theight: " << height << endl;
		
	}//---------print() 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//truck.h

#ifndef truck_h
#define truck_h

class truck{
	
	public:
		
	string type;
	string color;
	int length;
	int height;
	
	truck();
	
	truck(car);
	
	void print();
};

#endif 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//truck.cpp

#include "truck.h"

	truck::truck(){
		
		type = "truck";
		color = "white";
		length = 12;
		height = 8;
		
	}//-----constructor()
	
	truck::truck(car cobj){
		
		type = "truck";
		color = cobj.color;
		length = cobj.length;
		height = cobj.height;
		
	}//--------constructor(car)
	
	void truck::print(){
		
		cout << "type: " << type << "\tcolor: " << color << "\tlength: " << length <<"\theight: " << height << endl;
		
	}//--------print() 
closed account (10X9216C)
You need the forward declaration still. The point of the forward declaration is for the header to know that Truck exists. That's why you were getting "incomplete type". Moving the body into a source file let's you include the details of the Truck so that you can now use the details of the Truck (no longer incomplete type).
I went into a through explanation above about why you can't pass a forward reference by value.

Change truck.h line 17 to pass by reference. Make sure car is declared forward.

truck.cpp uses car, so you must include the car.h header.

Change car.h line 17 to passk truck by reference. Make sure truck is declared forward.
Pages: 12