Sign in to follow this  
quophyie

Using structs and namespaces from header in cpp files

Recommended Posts

Hi guys I am having a few problems with some structs that I have defined in my header file and want to use in my CPP file. The struct called "deck" is defined in a file called "Cards.h". In the corresponding CPP file called "Cards.cpp" when I try to use the struct "deck", I get a lot of errors from the compiler as displayed in my compiler errors below. I have tried all manner of things including defing variables without the scope ie.. deck dec; in the cpp file but nothing seems to work. I was hoping one of you guys will point out to me if there is something that I'm doing wrong cos I cannot see it. Also, one other thing, If I define a namespace in my header file, am I able to use it in my cpp file? I'm only asking this cos I have defined a name called "pack" in my header file but when I try to use it in my cpp file, get an error saying that "pack is not s namespace name" as is illustrated in my compiler errors. I am using mingw 3.4.5. Please Help!!! The Header file
#ifndef CARDS_H_
#define CARDS_H_
#include <iostream>
#include <string>
#include <vector>
 
 
 
namespace pack{
 
 
typedef struct sample
{
int a;
char b, c;
}
SAMPLE_STRUCT;
//////
}
 
 
class Cards
{
 
public:
 
 
 
 
 
 
Cards();
virtual ~Cards();
 
 
struct deck{
 
// this holds the description of the card e.g. "King Of"
string card_name;
 
//card type e.g. "Hearts", Spades, etc
string card_type;
/*
* the value of the card e.g, 2,3 6 etc Note that Jack = 10
* Queen = 11, King = 12, Ace = 13
*/
int card_value;
};
 
deck getCard();
};
 
 
 
 
 
#endif /*CARDS_H_*/

the cpp file
#include "Cards.h"
#include <iostream>
#include <vector>
 
using namespace std;
using namespace pack;
 
class Cards{
 
 
 
public:
 
Cards();
~Cards();
 
Cards::deck getCard();
Cards::deck dec;
 
};
 
 
 
Cards::Cards()
{
 
 
}
 
Cards::~Cards()
{
}
 
Cards::deck Cards::getCard(){
 
 
}
Compiler Errors: **** Build of configuration Debug for project Poker **** **** Internal Builder is used for build **** g++ -O0 -g3 -Wall -c -fmessage-length=0 -oCards.o ..\Cards.cpp ..\Cards.cpp:9: error: `pack' is not a namespace-name ..\Cards.cpp:9: error: expected namespace-name before ';' token ..\Cards.cpp:20:2: warning: "/*" within comment ..\Cards.cpp:46: error: expected `;' before "getCard" ..\Cards.cpp:47: error: expected `;' before "dec" ..\Cards.cpp:63: error: expected constructor, destructor, or type conversion before "Cards" Build error occurred, build is stopped Time consumed: 14359 ms.

Share this post


Link to post
Share on other sites
Is this your actual code? It seems extremely unlikely as the line numbers don't match up with your error messages and the fact that you should be getting errors in your header for not prefixing string with std::.

Share this post


Link to post
Share on other sites
This is the actual code. The line numbers in the error does not match up with the posted code cos I compiled it and pasted the error here and then removed some comment lines from the code before posting the code itself. Anyway, I have appended std:: to strings in the header file and its still not working. The problem in not in the header file, its in the cpp file.

Share this post


Link to post
Share on other sites
I'm not sure what you mean by "violating the one definition rule for the class cards" but the code itself has not changed. the only difference btn the posted code and the one used to generate the error is that I deleted some comment lines before posting the code here. In essence, the code posted is the same as the one used to generate the error. The only difference is one has had some comment lines deleted.

Share this post


Link to post
Share on other sites
To quote The C++ programming language " A given class must be defined exactly once in a program. ... That is two definitions of a class are accepted as examples of the same unique definition if and only if
1. they appear in different translation units
2. they are token for token identical
3. the meanings of those tokens are the same in both translation units. "

In your header you have namespace pack with a struct in it. This is followed by the definition of a class named Cards. This class has a virtual destructor, and a struct called deck. In your Cpp file you have another definition of the class Cards it has a non virtual destructor, and an instance of the deck struct but no definition of it. Therefore you violate the one definition rule because the two definitions are not in different translation units, and the definitions are not token for token identical.

Share this post


Link to post
Share on other sites
Cool. I understand what you mean. Presumably you are saying that the struct deck should also be defined in cpp file. But does that not defeat the purpose of the object? I thought that if you included a header file, then you should be able to use all the items in the header file without having to define them again? If thats the case, then why then the need to redefine deck in the cpp file? I have also tried adding deck in the pack namespace but I keep getting a an error that the namespace pack is not a namepace.

Share this post


Link to post
Share on other sites
Quote:

Cool. I understand what you mean. Presumably you are saying that the struct deck should also be defined in cpp file.


No, that's not what he's saying at all.

You have the class definition for Cards in both the header and cpp file. You can only have one definition of a class (or anything for that matter). Get rid of that and see if your code compiles (I doubt it, but at least the errors should be better).

Also in C++ you don't need to use typedef to name a struct. You can simply use the syntax:

struct structname
{
//code goes here...
};

But that's just me being picky.

Share this post


Link to post
Share on other sites
Thanks all of you who helped me understand this better. I finally overcame this problem by defining the struct and class in a namespace in the header file and to get access to the struct and methods in the namespace from the cpp, I used the scope operator. I know that for some experts, this may be obvious but for us newbies, it can sometimes be mind boggling to get our heads around these things. Anyway here is the code.

the header



#ifndef CARDS_H_
#define CARDS_H_
#include <iostream>
#include <string>
#include <vector>

using namespace std;

namespace pack{


class Cards
{

public:
Cards();
~Cards();

struct deck{

// this holds the description of the card e.g. "King Of"
std::string card_name;

//card type e.g. "Hearts", Spades, etc
std::string card_type;
/*
* the value of the card e.g, 2,3 6 etc Note that Jack = 10
* Queen = 11, King = 12, Ace = 13
*/

int card_value;
};

deck getCard();

};

}
#endif /*CARDS_H_*/



the cpp file




#include "Cards.h"
#include <iostream>
#include <vector>

using namespace std;

class Cards{
public:
Cards();
~Cards();

/*defines a deck with a return type of deck i.e. Note that
* the return type deck is from the namespace pack which is declared and defined in
* the the header file "Cards.h"
*/

pack::Cards::deck dec;

/*defines a getCard with a return type of deck i.e. Note that
* the return type deck is from the namespace pack which is declared and defined in
* the the header file "Cards.h"
*/

pack::Cards::deck getCard();
};

Cards::Cards()
{


}

Cards::~Cards()
{
}

pack::Cards::deck Cards::getCard(){

return dec;
}



Share this post


Link to post
Share on other sites
Hi

Ok now you have two Cards classes. One is called pack:Cards and is defined in the h file. The other is called Cards and is defined in the cpp file.

The reason the compiler don't complain about 'redefining the Cards class' is that they are defined in different scopes.

If you don't mind I think its safe to say that this is not what you want.
The problem you have here is that you define the Cards class twice.
All you need to do is to remove the Cards class in the cpp file.

.h:

#include <iostream>
#include <string>
#include <vector>

using namespace std;

namespace pack {

class Cards {

public:
Cards();
~Cards();

struct deck {
std::string card_name;
std::string card_type;
int card_value;
};

deck getCard();
};

}



.cpp:

namespace pack {

Cards::Cards()
{
}

Cards::~Cards()
{
}

Cards::deck Cards::getCard()
{
return deck(); // Just to satisfy the compiler for now...
}

}



Again if you don't mind I would suggest a slightly different approach. Note that there is many ways to go about designing the structures for the game. This is just one.

.h:

#include <iostream>
#include <string>
#include <vector>

using namespace std;

namespace Poker
{
/*
Define a single card. This is the most basic building block in a card game.
Both a hand and the deck is really no more than collections of this class
*/

class Card
{
public:

...

std::string card_name;
std::string card_type;
int card_value;
};

/*
I bet we could make a class that could represent both a hand and a deck, after all the only major difference between them is how many cards they hold.
To keep things clear and simple I suggest one class for each.
*/

class Deck
{
public:

...

// Empty the deck vector and refill/shuffle it. This function can also be called in the Deck constructor to initalize the deck
void Reset();

Card getCard(); // Remove a card from the deck and return it

// Tip: The 'algorithm' header has a function called random_shuffle that we can use to randomize the cards in the deck vector
void Shuffle();

private:

vector<Card> deck;
};

class Hand
{
public:

...

void Reset(); // Empty the hand
Card getCard(); // Remove a card from the hand and return it
void addCard(); // Add a card

private:

vector<Card> hand;
};

}

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this