How Do I Do This (Class Definition)?

M

Mike Copeland

I'm trying to define and use a class, and I'm confused about what to
do and how to correct the compiler diagnostics I get. Here is the code
I have in my .h file:

class ShadowData
{
public:
char shadowRace; // shadow race event
char realRace; // "real" race event
int shadowBib; // shadow Bib#
int realBib; // "real" Bib#
};
bool shadowBibSort(const ShadowData &d1, const ShadowData &d2)
{
return d1.shadowBib < d2.shadowBib;
}
bool realBibSort(const ShadowData &d1, const ShadowData &d2)
{
return d1.realBib < d2.realBib;
}
typedef vector<ShadowData> ShadowVector;
extern ShadowVector shadowVect;
typedef ShadowVector::iterator shadowIter;
extern ShadowIter shadowIter; // Error on this line!

I get a compiler error on the noted line when I have the following
code in the .cpp file from which I invoke this declaration:
ShadowVector shadowVect; // declare global vector object
ShadowIter shadowIter; // declare global iterator object

I'm embarrassed to admit I can't see what I'm doing wrong. 8<{{
Please advise. TIA
 
S

Stefan Ram

typedef ShadowVector::iterator shadowIter;
extern ShadowIter shadowIter; // Error on this line!

Did you intend one of the lower-case s to be upper case?
 
M

Mike Copeland

Did you intend one of the lower-case s to be upper case?
No, and I did find the particular error. The definitions should have
been:

typedef vector<ShadowData> ShadowVector;
extern ShadowVector shadowVect;
extern ShadowVector::iterator shadowIter;

However, I now have a packaging/linkage error (21 of them, in fact!).
The above code is in myClass.h and the declarations are in myClass.cpp.

ShadowVector shadowVect; // declare global object
ShadowVector::iterator shadowIter; // declare global iterator

That file compiles, but using it in a larger program causes linkage
errors of multiple definitions. Clearly, I'm misusing the class concept
in my larger program, and something is misdefinied. I don't know what
it is, nor what to do here. 8<{{
How should this be structured in myClass.h, myClass.cpp and the main
program? TIA
 
J

Jorgen Grahn

I'm trying to define and use a class, and I'm confused about what to
do and how to correct the compiler diagnostics I get. Here is the code
I have in my .h file:

class ShadowData
{
public:
char shadowRace; // shadow race event
char realRace; // "real" race event
int shadowBib; // shadow Bib#
int realBib; // "real" Bib#
};
bool shadowBibSort(const ShadowData &d1, const ShadowData &d2)
{
return d1.shadowBib < d2.shadowBib;
}

Don't call this one "sort" when it doesn't sort anything.
Call it shadowBibLess() or something, in analogy with std::less.

Since it's also not a member function, it should either be declared
"inline", or else just /declared/ here and /implemented/ in your .cpp
file. (For such a small and frequently called function, I'd use
inline.)
bool realBibSort(const ShadowData &d1, const ShadowData &d2)
{
return d1.realBib < d2.realBib;
}

Same here.
typedef vector<ShadowData> ShadowVector;
extern ShadowVector shadowVect;
typedef ShadowVector::iterator shadowIter;
extern ShadowIter shadowIter; // Error on this line!

I get a compiler error on the noted line when I have the following
code in the .cpp file from which I invoke this declaration:
ShadowVector shadowVect; // declare global vector object
ShadowIter shadowIter; // declare global iterator object

Avoid this. What you normally do when you design a class is to define
the class type itself in a header file, maybe related typedefs and
loose functions like your ShadowVector and shadowIter, and implement
the parts that are still missing in the .cpp file.

You should typically *not* do what you do here: declare a single,
global ShadowVector object. Let the users of your class declare their
own objects, as many as they want.

/Jorgen
 
J

Juha Nieminen

Mike Copeland said:
That file compiles, but using it in a larger program causes linkage
errors of multiple definitions.

Multiple definitions of what?

At least your functions aren't inline, which will cause linker errors.
 
F

Fred

   No, and I did find the particular error.  The definitions shouldhave
been:

typedef vector<ShadowData>     ShadowVector;
extern  ShadowVector           shadowVect;
extern  ShadowVector::iterator shadowIter;

   However, I now have a packaging/linkage error (21 of them, in fact!).  
The above code is in myClass.h and the declarations are in myClass.cpp.

    ShadowVector  shadowVect;    // declare global object
    ShadowVector::iterator shadowIter;   // declare global iterator

   That file compiles, but using it in a larger program causes linkage
errors of multiple definitions.  Clearly, I'm misusing the class concept
in my larger program, and something is misdefinied.  I don't know what
it is, nor what to do here.  8<{{
   How should this be structured in myClass.h, myClass.cpp and the main
program?  TIA

I would probably declare shadowBibSort() and realBibSort() as static
functions within the class:

class ShadowData
{
public:
char shadowRace; // shadow race event
char realRace; // "real" race event
int shadowBib; // shadow Bib#
int realBib; // "real" Bib#

static bool realBibSort(const ShadowData &d1, const ShadowData
&d2);
static bool shadowBibSort(const ShadowData &d1, const ShadowData
&d2);
};

and then define them in the .cpp file.

As it is, you have defined the two non-class functions in the header;
if the header is included in more than one .cpp file, you get
multiple definitions.
 
M

Mike Copeland

[deleted...]

Your comments were very helpful - and my compiler errors are gone!
Here's what I've done...but I have some new questions:

class ShadowData
{
public:
char shadowRace; // shadow race event
char realRace; // "real" race event
int shadowBib; // shadow Bib#
int realBib; // "real" Bib#

bool shadowBibLess(const ShadowData &d1, const ShadowData &d2)
{
return d1.shadowBib < d2.shadowBib;
}
bool realBibLess(const ShadowData &d1, const ShadowData &d2)
{
return d1.realBib < d2.realBib;
}
} ;
typedef vector<ShadowData> ShadowVector;
extern ShadowVector shadowVect;
extern ShadowVector::iterator shadowIter;

Although this compiles, I don't know if it's what I want. The point
of my implementation is to construct a vector of elements, each of which
contains a set of the variables (2 char & 2 int variables). As I
understand it, the above will create an object that contains not only
the data variables but the 2 bool procedures, too. Is that what I need?
I would think that I want to use the vector sort with either of the 2
procedures on the vector, and that having as many subprograms as I have
objects isn't what I want. It seems to me I want to execute the cool
procedures outside of the vector object, is that not so?
If so, how do I declare these procedures in the .h/.cpp
implementation, and how do I declare a structure of the data variables
that will become a vector element?
Thanks again for your help (and patience). 8<}}
 
J

Jorgen Grahn

[deleted...]

Your comments were very helpful - and my compiler errors are gone!
Here's what I've done...but I have some new questions:

class ShadowData
{
public:
char shadowRace; // shadow race event
char realRace; // "real" race event
int shadowBib; // shadow Bib#
int realBib; // "real" Bib#

bool shadowBibLess(const ShadowData &d1, const ShadowData &d2)
{
return d1.shadowBib < d2.shadowBib;
}
bool realBibLess(const ShadowData &d1, const ShadowData &d2)
{
return d1.realBib < d2.realBib;
}
} ;
typedef vector<ShadowData> ShadowVector;
extern ShadowVector shadowVect;
extern ShadowVector::iterator shadowIter;

Although this compiles, I don't know if it's what I want. The point
of my implementation is to construct a vector of elements, each of which
contains a set of the variables (2 char & 2 int variables). As I
understand it, the above will create an object that contains not only
the data variables but the 2 bool procedures, too. Is that what I need?

Hm, I didn't really suggest that. Now these are member functions,
and they deal with three objects: *this, d1 and d2. Make them member
functions which ask "am I less than that other ShadowData?" instead:

bool shadowBibLess(const ShadowData& other) const
{
return shadowBib < other.shadowBib;
}

That's a perfectly normal way of doing it.
I would think that I want to use the vector sort with either of the 2
procedures on the vector, and that having as many subprograms as I have
objects isn't what I want. It seems to me I want to execute the cool
procedures outside of the vector object, is that not so?

Your client code needs a way (or two ways) to compare ShadowDatas, and
there are several ways to make that happen: plain functions like you
had originally (inline or not) or member functions like above.
If so, how do I declare these procedures in the .h/.cpp
implementation, and how do I declare a structure of the data variables
that will become a vector element?
Thanks again for your help (and patience). 8<}}

My time has run out; hopefully others can explain better.

I get the impression that you're coming from C (or Java?). Perhaps
you need to sit down and read a book on C++. There are some
fundamental things you haven't grasped yet, and they're hard to learn
by asking people on Usenet.

/Jorgen
 
M

Mike Copeland

Hm, I didn't really suggest that. Now these are member functions,
and they deal with three objects: *this, d1 and d2. Make them member
functions which ask "am I less than that other ShadowData?" instead:

bool shadowBibLess(const ShadowData& other) const
{
return shadowBib < other.shadowBib;
}

That's a perfectly normal way of doing it.

Ullp, it's getting messier for me. Here's a complete programs source
that now won't compile - because the sort statement expects 2 arguments,
not 3. I really don't know how to use these member functions... 8<{{
#pragma warning (disable:4786)
#include <vector>
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <string>
using namespace std;
//--------------------------------------------------------------------
class TeamData
{
public:
string ID; // Team Code (TId4)
string TeamName; // Team's Name
bool Added; // Added to working stack of teams
char TypeCode; // Team type Code
int CTM1; // Count of Team Members-1
int CTM2; // Count of Team Members-2
bool teamIdLess(const TeamData &other)
{
return ID < other.ID;
}
bool teamNameLess(const TeamData &other)
{
return TeamName < other.TeamName;
}
} ;

typedef vector<TeamData> TeamVector;
typedef TeamVector::iterator teamIter;
TeamVector teamVector;

//////////////////////////////////////////////////////////
int main()
{
TeamData data;
teamIter tIter;
data.CTM1 = data.CTM2 = 0, data.Added = true;
data.ID = "B321", data.TeamName = "BEAT JABBA", data.TypeCode = 'G';
teamVector.push_back(data);
data.ID = "C162", data.TeamName = "COBRA KAI", data.TypeCode = 'M';
teamVector.push_back(data);
data.ID = "R241", data.TeamName = "RACELAB", data.TypeCode = 'B';
teamVector.push_back(data);
data.ID = "R521", data.TeamName = "RUNNING IS FOR EMERGENCIES",
data.TypeCode = 'H';
teamVector.push_back(data);
data.ID = "S341", data.TeamName = "SADDLEBROOKE", data.TypeCode =
'X';
teamVector.push_back(data);
data.ID = "T235", data.TeamName = "TEST TEAM", data.TypeCode = '?';
teamVector.push_back(data);
data.ID = "T525", data.TeamName = "TEAM CHANCES", data.TypeCode =
'X';
teamVector.push_back(data);
data.ID = "T536", data.TeamName = "TEAM TRIPLE SPORTS",
data.TypeCode = 'S';
teamVector.push_back(data);
data.ID = "1001", data.TeamName = "QUEST", data.TypeCode = 'C';
teamVector.push_back(data);
data.ID = "1002", data.TeamName = "RUNNER'S DEN", data.TypeCode =
'B';
teamVector.push_back(data);
data.ID = "7000", data.TeamName = "QUEST CLUB", data.TypeCode = 'C';
teamVector.push_back(data);
size_t tSize = teamVector.size();
///////////////////////////////////////////////////////////
sort(teamVector.begin(), teamVector.end(), teamVector.teamIdLess);
///////////////////////////////////////////////////////////
return 0;
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,225
Members
46,815
Latest member
treekmostly22

Latest Threads

Top