Placing Classes in Separate Files

Started by
5 comments, last by rip-off 12 years, 2 months ago
I felt like I understood classes enough to start placing them in separate files, so I watched a tutorial, but it didn't go as far as adding the public and private parts. I can get as far as adding a simple cout << "whatever"; but once I actually try to make a functional class, I get these errors...

Character.cpp|8|error: expected ')' before ',' token|
Character.cpp|8|error: expected initializer before ')' token|
||=== Build finished: 2 errors, 0 warnings ===|

What am I doing wrong?


character.h
#ifndef CHARACTER_H
#define CHARACTER_H

class hieght
{
public:
hieght();
};
#endif // CHARACTER_H


Character.cpp
#include <iostream>
#include <string>
#include "Character.h"
using namespace std;

hieght::hieght(f, g) // error is pointing here
{
setHigh(f);
setLow(g);
public;
setHigh(h)
{
high = h;
}
setLow(l)
{
low = l;
}
int getLow()
{
return low;
}
int getHigh()
{
return high;
}
private:
int low;
int high;
}
Advertisement
Are you sure you're only getting 2 build errors?
Firstly, the definition of your constructor takes no argument but your implementation is taking 2 arguments f and g.....
Secondly, we don't define a class's member function inside its constructor... all the private and public parts should be in the class definition not the constructor.
Thirdly, you are not providing any type to any of the variable used... in c++ there is no default type nor is it typeless like python...

Ok!! so a working version of your code might be...
character.h
#ifndef CHARACTER_H
#define CHARACTER_H
class hieght
{
public:
hieght(int f, int g);
int GetHigh();
int GetLow();
void SetHigh(int h);
void SetLow(int l);
private:
int low;
int high;
};
#endif // CHARACTER_H


character.cpp#include <iostream>
#include <string>
#include "Character.h"
using namespace std;
hieght::hieght(int f, int g) // error is pointing here
{
setHigh(f);
setLow(g);
}
void hieght::setHigh(int h)
{
high = h;
}
void hieght::setLow(int l)
{
low = l;
}
int hieght::GetLow()
{
return low;
}
int hieght::GetHigh()
{
return high;
}
}
I saw you didn't have a public or private section in the class. Am I suppose to leave that out?

Here's my new list of errors, followed by my current code.

Character.cpp||In constructor 'height::height(int, int)':|
Character.cpp|14|error: expected primary-expression before 'public'|
Character.cpp|14|error: expected ';' before 'public'|
Character.cpp|16|error: a function-definition is not allowed here before '{' token|
Character.cpp|20|error: a function-definition is not allowed here before '{' token|
Character.cpp|24|error: a function-definition is not allowed here before '{' token|
Character.cpp|28|error: a function-definition is not allowed here before '{' token|
Character.cpp|31|error: expected primary-expression before 'private'|
Character.cpp|31|error: expected ';' before 'private'|
Character.cpp|33|warning: unused variable 'high'|
||=== Build finished: 8 errors, 1 warnings ===|

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

character.cpp
height::height(int f, int g)
{
{
setHigh(f);
setLow(g);
}
public;
void setHigh(int h)
{
high = h;
}
void setLow(int l)
{
low = l;
}
int getLow()
{
return low;
}
int getHigh()
{
return high;
}
private:
int low;
int high;
}


Character.h
#ifndef CHARACTER_H
#define CHARACTER_H

class height
{
public:
height(int f, int g);
void setHigh(int h);
void setLow(int l);
int getLow();
int getHigh();
private:
int low;
int high;};
#endif // CHARACTER_H
Look at your character.cpp code compared to newbie_gamer's -- the syntax is completely different (wrong).
Where are you learning about class syntax from?
height::height(int f, int g)//this is a function -- the 'height' class's constructor function
{
{//this brace doesn't need to be here, we're already in the function body
setHigh(f);
setLow(g);
}
//the function should end here with a } !!

//now we should be back at global file scope, but you're missing a "}" so we're still inside a function body

public;//no, this doesn't belong here -- this goes in the class body in the header.
void setHigh(int h)//you're still inside a function body - you're trying to write this function inside another function.
{//you want to be at global file scope and use "void height::setHigh(int h)" to implement this function.
high = h;
}
private://again, you're not in the class body here. The class body is in the header. This stuff should be in the class body in the header.
int low;
int high;
}
You also have a typo- In character.cpp following "public" should be a colon, not a semicolon.
I've been watching thenewbostons video tutorials. I feel like he barely touched how to really put a class file in a separate file. I started off learning c++ reading the stuff on learncpp.com. I went back there and got it working perfectly. Here's what I did. I see that both what newbie_gamer and I did work, but is his way a more correct way to do it?

Character.h
#ifndef CHARACTER_H
#define CHARACTER_H

class height
{
public:
height(int f, int g);
void setHigh(int h);
void setLow(int l);
int getLow()
{
return low;
}
int getHigh()
{
return high;
}
private:
int low;
int high;
};
#endif // CHARACTER_H


Character.cpp
#include <iostream>
#include <string>
#include "Character.h"
using namespace std;

height::height(int f, int g)
{
setHigh(f);
setLow(g);
}
void height::setHigh(int h)
{
high = h;
}
void height::setLow(int l)
{
low = l;
}

... is his way a more correct way to do it?
[/quote]
That looks like almost the right way to separate a class into a header/source file. Generally one makes the class name and the header name match, for consistency and ease of maintenance.

One other important thing is to make the source file always include its own header as the very first line. Why? To ensure that the header compiles fine in isolation.

Imagine we have another file, main.cpp, it looks like this:

#include "Character.h"

int main() {

}

That would compile fine.

Now, imagine we rename the included class to "Character", and give them a std::string name member variable, without adding #include<string> to the header. The current version of Character.cpp will compile file, because at the point where the compiler includes Character.h the string header has already been included.

Not so with main.cpp - it will report an error! The problem is that the Character header has a hidden dependency on <string>, which means that any file wanting to include Character must ensure it includes <string> first. We don't want this. First, it is very brittle. If we added a std::vector<> to Character, we don't want to add an include in every file that happens to include character. It makes sense just to add the include to the header itself.

So, by moving #include "Character.h" to the very first line of Character.cpp, we ensure that the Character header can be compiled alone - it has no hidden dependencies.

[hr]

Minor points - you are doing a bit of unnecessary work in the source file, by including the unused standard headers and using namespace std.

The class itself does look a little suspect though. One might think there is a natural invariant to be enforced between "high" and "low". I'm not sure how these relate to the class's purpose though, indeed the class's purpose is vague.

This topic is closed to new replies.

Advertisement