0
101 Dec 16, 2005 at 13:53

Another really silly new guy question… I am ok with using header files and stuff for strait cpp functions.. but how do you seperate an entire class into a seprate file?

here is a real simple code example… .. ..

#include <iostream>
#include <string>
#include <vector>
using namespace std;

class charicter_c {
public:
void listInventory();
private:
vector <string> inventory_c;
};
inventory_c.push_back(item);
}

void charicter_c::listInventory() {
for (int i=0; i < inventory_c.size(); ++i)
cout << inventory_c[i] << endl;
}

int main ()
{
string item;
item = "Axe";
charicter_c input1;
input1.listInventory();

cout << "\n\n\n\nPlease press enter to exit program.";
cin.ignore(cin.rdbuf()->in_avail() + 1);
return 0;
}


If I wanted to split the class into a seprate file.. how would I do that…

as I understand it I need to make a header file and a cpp file..

charicter.h / charicter.cpp

in the cpp I would put all the class stuff….

class charicter_c {
public:
void listInventory();
private:
vector <string> inventory_c;
};
inventory_c.push_back(item);
}

void charicter_c::listInventory() {
for (int i=0; i < inventory_c.size(); ++i)
cout << inventory_c[i] << endl;
}


as well as a include “charicter.h”, I would also add that to the main.cpp. What do I need to put into the header file itself… and am I going about this the rigth way?

22 Replies

0
101 Dec 16, 2005 at 14:02

Usually you will just declare the class in the header file and specify the implementation of that class in the .cpp file. What I mean by “declaring the class” is that you specify the data members and the interface of the member functions. You shouldn’t implement the functions in the header file. For example :

/* test.h */
#ifndef TEST_H
#define TEST_H
class test {
int id;
char name[10];
public:
test(void);
int getId(void);
};
#endif


and

/* test.cpp */
#include "test.h"
test :: test(void) {
id=2;
}
int test :: getId(void) {
return id;
}


Hope that helps.

0
101 Dec 16, 2005 at 14:30

Hi

/* main.cpp */

#include <iostream>
#include <string>
#include "test.h"
int main ()
{
return 0;
}

0
101 Dec 16, 2005 at 14:37

great thanks guys… I was unsure wat to put in the header.. so the entire class “definition” with all the variables and the functions decleratons in the header.. Then the actual functions themselves in the cpp bit…

@roxtar

#ifndef TEST_H
#define TEST_H

I should add this to all header files shouldn’t I .. I looked them up and they mean that the .h files will only be loaded once?

If I have to use things like #include <strings> in the header and external cpp files should I also add ifndef/define for them as well??

0
101 Dec 16, 2005 at 14:57

It is a good practice to have the #ifndef #define etc in your header files so that you don’t end up including them more than once. I usually follow the convention of doing something like

#ifndef HEADER_FILE_NAME_H
.
.
.
#endif


If you are including any other header files like string.h etc you don’t need to do separate #ifndef #defines for them, as it is already done in those header files.

0
101 Dec 16, 2005 at 15:32

For many cases it’s not really that useful to split classes for the separate “implementation” and “header” file. I see it quite often that people split all the classes they write without thinking if that’s really needed and without knowing what kind of implications it has.

There are reasons and situations when the splitting is a good idea, but there also are situations where it’s not…that said I would like to rant about the whole #include system C++ has but would go bit off-topic.. :)

0
101 Dec 16, 2005 at 15:45

@roxtar - Thanks for the tips.. cheers.

@juhnu - You are right I do not really understand “what kind of implications it has.” to split the files up.. I am mainly doing it as a way of understanding how seperate files function as well as making “seperating” all the code up so I can read it easyer…. it seams logical to me to have everything split up where you can as a way to just make the code easyer to read. Mabey a better way to do it would be to group a bunch of classes that relate to a simular “thing-e-ma-bobs” in the program. So you get the code seperate for easy reading latter but minimize the seprate files… as well as keeping related code all in the one place.

0
102 Dec 16, 2005 at 16:08

The way you seperate your code is usually a matter of personal taste and coding standards. There are some exceptions.

Typically, you want to keep the number of dependencies to a minimum. For example, say class A uses class B internally, but class C only uses class A and doesn’t care about class B. It that case, it makes sense to hide class A’s use of class B from class C. In doing so, making changes to class B’s interface does not require a recompile of class C.

Could that have been any more obtuse? :blink:

0
101 Dec 16, 2005 at 16:10

I personally always do the .hpp/.cpp split myself. It lowers build times when my implementation changes but my interface does not, which allows me to develop faster.

In cases where inlining is necessary, that’s an optimization that can be done later.

0
101 Dec 16, 2005 at 16:10

@monjardin: Sounds like you’re setting up someone to talk about forward declaring. :)

0
102 Dec 16, 2005 at 16:11

That’s true eddie. You can always mash stuff together after you getting it working and “know” it won’t change anymore.

0
102 Dec 16, 2005 at 16:13

@eddie: We’re stomping on each others’ posts again. :p Yes, the OP should probably look into forward declarations soon.

0
101 Dec 16, 2005 at 17:36

@monjardin: Shall we dance? :)

I’m a big believer in Knuth’s saying: “Premature optimization is the root of all evil”. It applies to everything, from inlining to code layout to actual algorithm design.

Get it working first, be happy with it, and then massage it to the specs you need it to be.

</opinion> :)

0
101 Dec 16, 2005 at 18:19

@eddie

@monjardin: Shall we dance? :)

I’m a big believer in Knuth’s saying: “Premature optimization is the root of all evil”. It applies to everything, from inlining to code layout to actual algorithm design.

Get it working first, be happy with it, and then massage it to the specs you need it to be.

</opinion> :)

In that same line of thought, How do you know what to optimize, if you haven’t finished your code and ran a profiler against it? Answer: You don’t. So don’t bother optimizing until your code works AND it is slow, if it runs as fast as you need it to, don’t break it by trying to optimize it.

0
101 Dec 16, 2005 at 18:32

Right on, brother Nodlehs, right on.

0
101 Dec 17, 2005 at 05:44

@eddie

I personally always do the .hpp/.cpp split myself. It lowers build times when my implementation changes but my interface does not, which allows me to develop faster.

It doesn’t necessarily lower the build times. For example if you have lots of small classes, it’s better to keep them all in the same compilation unit, especially if your compiler of choice doesn’t support precompiled headers.

There are pros and cons for the splitting, but it seems people tend to prefer it in every case. How does it improve readibility to keep declaration of member variables, implementation specific inner classes and method prototypes in one file, while keeping implementations of all the functions in another?

I can understand the idea of separating the public interface of a class and the private implementation, but C++ style of splitting doesn’t really do this. If the headers needn’t to contain private methods and member variables, it would be ok, but that’s not the case.

We are using abstract interfaces paradigm quite often and separating an actual implementation class into two distinct files makes little sense here.

//public header ISomething.h
class ISomething {
public:
virtual void Do()=0;
}
//private implementation Something.cpp
class Something: public ISomething {
virtual void Do() {...}
}


Other situation is when you take advantage of the inner classes. They come in handy sometimes when you need to cross reference between two classes and when the other class is implementation specific to another. Of course you can try to split inner classes as well, but it really makes it hard to read.

Don’t get me wrong though. I’m personally using the splitting when it’s needed to lower compilation dependencies or for other justificated purpose, but thats probably 20% of the classes or less.

0
102 Dec 17, 2005 at 15:59

You can also use the pimpl (pointer-to-implementation) idiom to avoid the necessity of virtual function calls and inhereitence.

// something.hpp
class SomethingPrivate; // forward declaration
class Something
{
SomethingPrivate *pimpl;
public:
... a bunch of functions that will call the pimpl to do the work
};

// something.cpp
class SomethingPrivate
{
... all of your private member variables
public:
... the real implementation of the Something methods
};

... the implementation of the Something methods that redirect to the pimpl


If you need inner classes, then you can fully define them in the pimpl class in the same file and noone is the wiser. ;)

0
165 Dec 17, 2005 at 19:24

Yeah, but the fact that you have to use something like the pImpl idiom is rather annoying. In truth, it’s a hack to get around the fact that C++ doesn’t allow proper implementation/interface separation.

(In C++’s defense, the reason it needs private variables to be declared in the definition is so it knows how big the class is in case you need to allocate space for an object of it. Otherwise all objects of the class would have to go on the heap, since it wouldn’t know their sizes until link time.)

Personally, I use abstract interfaces and factories when I want to hide implementation completely. The abstract stuff goes in the header file and then a concrete class implementation deriving from the interface is hidden in a .cpp file.

0
101 Dec 17, 2005 at 19:38

monjardin: actually, pimpl stands for “private implementation” ;)

0
101 Dec 17, 2005 at 19:46

@juhnu

It doesn’t necessarily lower the build times. For example if you have lots of small classes, it’s better to keep them all in the same compilation unit, especially if your compiler of choice doesn’t support precompiled headers.

Right. Perhaps I stated it wrong. It often helps reduce rebuild times.

At my last work place, they had one file called ‘library.hpp’ that included *every* other header in the module. You changed *one* thing, and it would cause everything in your entire tree to rebuild. Tres annoying.

I’ve known some people to still do the split-your-classes thing, but then have one master .cpp file that #includes everything. I’ve never done it myself, but I understand it makes compilation ridiculously fast.

You also bring up a good point about hiding the private implementation. I agree that C++ doesn’t do it that well, although understandably, since C++ has to guarantee structure layout of it’s private members. Still, it would be nice if I could achieve the separation of implementation from definition, without resorting to pimpl. (I’ve never liked pimpl: granted, I’ve never really seen it in all it’s glory, so it could be a bad prejudice to have).

0
101 Dec 17, 2005 at 21:00

Forgive me for sounding quite ignorant, but instead of all of the #ifndef crap couldn’t you just write

#pragma once

0
101 Dec 17, 2005 at 21:41

@IrishFarmer

Forgive me for sounding quite ignorant, but instead of all of the #ifndef crap couldn’t you just write #pragma once

Definitely. If you’re using gcc 3.4.4 or greater, or MSVC.

But not all compilers support this. gcc I believe had a fit at one point, supported it, and then deprecated it, and now brought it back.

In short: you can use it if you know your compiler set. If you’re building a library for someone else’s consumption however, stick with the tried and true #ifndef.

<personal opinion>

I like the idea of #pragma once: it simplifies the #ifndef crap, but I wish it had a better name. I suppose it makes sense if you think about it, but I would’ve preferred something like #pragma include_only_once or some such.

Nitpicky, I know. :)

</personal opinion>

0
102 Dec 17, 2005 at 23:36

Sorry about mis-defining pimpl… it’s been awhile. As for seeing it in all it’s glory, the Qt library makes extensive use of it. At least it did as of version 3, I haven’t looked at 4. I don’t make use of it personally, prefering abstract bases class like the rest of you. I just thought it should be mentioned for thoroughness. :p