Custum Classes in Custom Headers

Started by
12 comments, last by Adam1942 14 years, 11 months ago
Hello everyone. This isn't a game programming issue, but its a programming issue none the less. A friend of mine asked me to create a program for him to determine a starting chemical based on a series of options that the user can select. Unfortunatley there are different options for the different types of chemcials (alcohols, ketones, etc). I figured the best approach would be to create a different class for each type of chemical. I quickly realized that a large amount of code would be required just to create these classes so I thought that maybe I should split them into different headers which I would then include in the main program. However I am having some trouble with headers. I started out with a base class with contains the 2 properties that all the different chemicals will have in common, but I can not get my header file to compile. Here is my code: chemical.h #ifndef GUARD_chemical_h #define GUARD_chemical_h #include<iostream> #include<string> using namespace std; class Chemical { public: ostream& operator <<(ostream& out); private: string startingMaterial; }; #endif chemical.cpp #include "chemical.h" using namespace std; ostream& operator <<(ostream& out) { out << startingMaterial; return out; } I'm sorry if this code is atrocious, i've never made custom headers before :(
Advertisement
Both look fine to me, except that in chemical.cpp, you need to specify that the function you're implementing is a member of the Chemical class:
ostream& Chemical::operator <<(ostream& out) { ... }


I'm not so convinced that you need a separate class for every different chemical type. Is there no way to parametrize the differences - that is, having a single, or a few, different classes, where the different chemical types are modeled by multiple instances that contain different values for certain aspects?

EDIT: Oh, and you'll want to remove that 'using namespace std' statement from your header file. It'll cause every other file that includes that header to also use the std namespace - this is sometimes called namespace pollution, as it goes against the purpose of namespaces (that is, to avoid name clashes).
Create-ivity - a game development blog Mouseover for more information.
So I'm guessing if I remove using namespace std from my .h file then i'll have to preface everything from that namespace with std:: right?

Also the header file still won't compile, It may be my compiler, I press compile and nothing happens. Normally I'd get a compilation complete message or a list of errors, but for the .h file i get nothing. I'm using Dev-C++ in case this happens to be a well documented issue.

As to wither or not a class for each chemical is the right route I can't really say. All I know is that my friend said they all (or most all) have different options, so the only option I saw was either create one super chemical class which had every single property or write a series of simpler classes. I chose multiple classes since it felt more organic to say "this is a ketone, it has property X and property Y" than to say "this instance of super chemical has property X and property Y, therefore its a ketone". I guess its just a matter of preferance.
Quote:Original post by Adam1942
So I'm guessing if I remove using namespace std from my .h file then i'll have to preface everything from that namespace with std:: right?

Yes, and that's a good thing.

Quote:Original post by Adam1942
Also the header file still won't compile, It may be my compiler, I press compile and nothing happens. Normally I'd get a compilation complete message or a list of errors, but for the .h file i get nothing. I'm using Dev-C++ in case this happens to be a well documented issue.

Header files are not compiled. Only source (.cpp) files are. Though when you #include "header.h", you are literally copying all of the contents in "header.h" into the current file (like your source file, which does get compiled).

Quote:Original post by Adam1942
As to wither or not a class for each chemical is the right route I can't really say. All I know is that my friend said they all (or most all) have different options, so the only option I saw was either create one super chemical class which had every single property or write a series of simpler classes. I chose multiple classes since it felt more organic to say "this is a ketone, it has property X and property Y" than to say "this instance of super chemical has property X and property Y, therefore its a ketone". I guess its just a matter of preferance.

It's not so much preference as it is what properties they hold and how those properties are used. You could probably group similar properties that all chemicals have (like molar mass, acidity, things like that) into the class. You could also create a list of properties (like a std::vector or std::map or something). I guess in the end it depends on what you want to do with those properties and how you're using them. Creating a class for every chemical seems like overkill though. There is definitely a way to simplify this.
[size=2][ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]
Well I may revise the implimination design once my friend gets me a list of all the chemical types and the properties he needs.

my .h file still has a couple errors in it, but I think they are all tied into this one:

declaration of 'operator<<' as non-function.

Here's the code again

#ifndef GUARD_chemical_h
#define GUARD_chemical_h

#include<iostream>
#include<string>

class Chemical
{
public:
ostream& operator<<(ostream& out); //error is in this line

private:
std::string startingMaterial;
};

#endif

ostream also resides in the std namespace, so just like string, it needs the std:: namespace specifier.
Create-ivity - a game development blog Mouseover for more information.
Oops! It still isn't working though, I've realized another mistake in my cpp file, but that also didn't get rid of the error. I do know it is a namespace issue since if I switch the postions of using namespace std and #include "chemical.h" in the cpp file the error disappears. Here is the code again for referance:

chemical.h

#ifndef GUARD_chemical_h
#define GUARD_chemical_h

#include<iostream>
#include<string>

class Chemical
{
public:

std::ostream& operator<<(ostream& out);

private:
std::string startingMaterial;
};

#endif

chemical.cpp

#include "chemical.h"
using namespace std;


ostream& Chemical::operator <<(ostream& out)
{
out << startingMaterial;
return out;
}

btw should I be using std:: in the cpp file as well?












Check your header carefully. You've still forgotten the namespace identifier somewhere.

'Using' a namespace in a .cpp file is ok, if you're using items from that namespace a lot... namespaces are mostly there to prevent name clashes, so if there's a risk for that, you'd better just prefix everything with it's namespace. In this case, you've stated that you're using the std namespace, so everything from that namespace no longer needs the std:: prefix in that .cpp file.
Create-ivity - a game development blog Mouseover for more information.
Quote:Original post by Captain P
'Using' a namespace in a .cpp file is ok, if you're using items from that namespace a lot... namespaces are mostly there to prevent name clashes, so if there's a risk for that, you'd better just prefix everything with it's namespace. In this case, you've stated that you're using the std namespace, so everything from that namespace no longer needs the std:: prefix in that .cpp file.


Also, if you only use the items from std in a couple of functions or so, you can write the "using namespace std" inside the function definition.
You're doing it wrong. There, now I've got your attention. Overloading the << operator in a class/struct works like this

type_one operator << (type_two right_hand);

So in your code, out would be on the right hand of the << operator. Meaning your code would look like this:

Chemical chemical;
chemical << std::cout;

Obviously, this is not what you want. You have to declare a function that is a friend of Chemical, like this:
class Chemical{    public:        friend std::ostream& operator << (std::ostream& left_hand, const Chemical& right_hand);};// Later, you define the function like this:std::ostream& operator << (std::ostream& left_hand, const Chemical& right_hand){    left_hand << right_hand.startingMaterial;    return left_hand;}// And this is how you invoke the function:Chemical chemical;std::cout << chemical;

Of course, you'll probably want to pick better names for your parameters. I just wanted to make it clear where each parameter was in respect to the operator.

And make sure you're using std:: everywhere that deals with something from the std namespace (unless you've put a using directive, which we've talked about). Notice in your header the parameter doesn't have std:: prefixed to it. Try that and let us know how it goes.
[size=2][ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]

This topic is closed to new replies.

Advertisement