Use a class as a variable type in another class / include file.

Discussion in 'C++' started by Toke H?iland-J?rgensen, Dec 30, 2003.

  1. Hello. I am quite new to the c++ language, and am still trying to
    learn it. I recently discovered how using include files would allow me
    to split up my code into smaller segments, instead of having class
    definitions etc. in one big file (yay, major discovery...).

    My problem is this:

    When I define a class in one include file, and then try to instantiate
    it in another, I get compile-time errors saying the type is invalid.
    If i move the class definition of the class which instantiates the
    other class into the main .cpp-file i get no errors.

    How to solve this problem? I would like to have each class in seperate
    include files, but still be able to instantiate them inside each
    other.

    I am using Microsoft Visual C++ 6.0 on Windows XP.

    -Toke
    Toke H?iland-J?rgensen, Dec 30, 2003
    #1
    1. Advertising

  2. "Toke H?iland-J?rgensen" <> wrote...
    > Hello. I am quite new to the c++ language, and am still trying to
    > learn it. I recently discovered how using include files would allow me
    > to split up my code into smaller segments, instead of having class
    > definitions etc. in one big file (yay, major discovery...).
    >
    > My problem is this:
    >
    > When I define a class in one include file, and then try to instantiate
    > it in another, I get compile-time errors saying the type is invalid.
    > If i move the class definition of the class which instantiates the
    > other class into the main .cpp-file i get no errors.


    Try including the header with the first class into the source code
    with the other class:

    #include "myheader.h"

    >
    > How to solve this problem? I would like to have each class in seperate
    > include files, but still be able to instantiate them inside each
    > other.


    Also, see "forward declaration", it might be relevant, but hard to
    tell without the code.

    Victor
    Victor Bazarov, Dec 30, 2003
    #2
    1. Advertising

  3. Toke H?iland-J?rgensen

    Cy Edmunds Guest

    "Toke H?iland-J?rgensen" <> wrote in message
    news:...
    > Hello. I am quite new to the c++ language, and am still trying to
    > learn it. I recently discovered how using include files would allow me
    > to split up my code into smaller segments, instead of having class
    > definitions etc. in one big file (yay, major discovery...).
    >
    > My problem is this:
    >
    > When I define a class in one include file, and then try to instantiate
    > it in another, I get compile-time errors saying the type is invalid.
    > If i move the class definition of the class which instantiates the
    > other class into the main .cpp-file i get no errors.
    >
    > How to solve this problem? I would like to have each class in seperate
    > include files, but still be able to instantiate them inside each
    > other.
    >
    > I am using Microsoft Visual C++ 6.0 on Windows XP.
    >
    > -Toke


    I would suggest something like this:

    // main.cpp
    #include "myclass.h"
    int main() {// make use of myclass here}
    // end of file

    in one file,

    // myclass.h
    #if !defined MYCLASS_H
    #define MYCLASS_H
    class CoolClass
    {
    public:
    CoolClass();
    void amethod();
    // other stuff
    };
    #endif // end of file

    and finally

    // myclass.cpp
    #include "myclass.h"
    CoolClass::CoolClass()
    {
    // define constructor here
    }
    void CoolClass::amethod()
    {
    // define amethod here
    }
    // end of file

    main.cpp and myclass.cpp would be compiled into your project and myclass.h
    put into your include path.

    --
    Cy
    http://home.rochester.rr.com/cyhome/
    Cy Edmunds, Dec 30, 2003
    #3
  4. "Cy Edmunds" <> wrote in message news:<6A5Ib.90705$>...
    >
    > I would suggest something like this:


    <snip>

    > main.cpp and myclass.cpp would be compiled into your project and myclass.h
    > put into your include path.


    This is the structure I have been able to put together myself, and it
    works fine, just like you suggested. My problem is using myclass in
    another include file, e.g. myotherclass.cpp

    building on your structure:
    > // main.cpp
    > #include "myclass.h"
    > int main() {// make use of myclass here}
    > // end of file
    >
    > in one file,
    >
    > // myclass.h
    > #if !defined MYCLASS_H
    > #define MYCLASS_H
    > class CoolClass
    > {
    > public:
    > CoolClass();
    > void amethod();
    > // other stuff
    > };
    > #endif // end of file
    >
    > and finally
    >
    > // myclass.cpp
    > #include "myclass.h"
    > CoolClass::CoolClass()
    > {
    > // define constructor here
    > }
    > void CoolClass::amethod()
    > {
    > // define amethod here
    > }
    > // end of file
    >


    another class:

    //myotherclass.h
    #if !defined MYOTHERCLASS_H
    #define MYOTHERCLASS_H
    class QuiteCoolClass
    {
    public:
    QuiteCoolClass();
    void amethod();
    // other stuff
    };
    #endif // end of file

    //myotherclass.cpp

    #include "myotherclass.h"
    QuiteCoolClass::QuiteCoolClass()
    {
    // define constructor here
    }
    void QuiteCoolClass::amethod()
    {
    CoolClass coolClassInstance; //this is where the error is
    coolClassInstance.amethod(); //this doesn't work either
    // define amethod here
    }
    // end of file

    I get compile time errors when trying to do the above, whereas
    instantiating CoolClass in main() gives me no problems whatsoever,
    i.e. if I move the code from myotherclass.h and myotherclass.cpp into
    main.ccp, i get no errors.

    I hope this clarifies my problem a little... :)

    -Toke
    Toke H?iland-J?rgensen, Dec 31, 2003
    #4
  5. "Victor Bazarov" <> wrote in message news:<r55Ib.72445$VB2.142131@attbi_s51>...
    the
    > Try including the header with the first class into the source code
    > with the other class:
    >
    > #include "myheader.h"


    I tried that to no avail...

    > Also, see "forward declaration", it might be relevant, but hard to
    > tell without the code.


    I googled and found this document about forward declarations:
    http://www.adp-gmbh.ch/cpp/forward_decl.html
    I (think) i did what it suggests, but that didn't help either.

    Would it help if I posted the sourcecode of the offending files here?

    -Toke
    Toke H?iland-J?rgensen, Dec 31, 2003
    #5
  6. "Toke H?iland-J?rgensen" <> wrote...
    > "Victor Bazarov" <> wrote in message

    news:<r55Ib.72445$VB2.142131@attbi_s51>...
    > the
    > > Try including the header with the first class into the source code
    > > with the other class:
    > >
    > > #include "myheader.h"

    >
    > I tried that to no avail...
    >
    > > Also, see "forward declaration", it might be relevant, but hard to
    > > tell without the code.

    >
    > I googled and found this document about forward declarations:
    > http://www.adp-gmbh.ch/cpp/forward_decl.html
    > I (think) i did what it suggests, but that didn't help either.
    >
    > Would it help if I posted the sourcecode of the offending files here?


    Most certainly, yes. However, don't attach it, copy-and-paste it. Also,
    remove all non-essential parts of the code and make sure that after that
    it still compiles with exactly the same error message as you claim it does.

    V
    Victor Bazarov, Dec 31, 2003
    #6
  7. "Victor Bazarov" <> wrote in message news:<EPqIb.11490$I07.23677@attbi_s53>...
    > Most certainly, yes. However, don't attach it, copy-and-paste it. Also,
    > remove all non-essential parts of the code and make sure that after that
    > it still compiles with exactly the same error message as you claim it does.


    Okay...the program is an attempt at making a text adventure as an
    excercise...

    //adventure.cpp
    #include <iostream.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <fstream.h>
    #include <windows.h>

    const int WEAPON = 100;
    const int ARMOR = 101;
    const int CHARM = 102;
    const int TEXTMODE = 200;
    const int BINARYMODE = 201;
    const int NUMRANDOMS = 10000;
    const int EAST = 1;
    const int WEST = 2;
    const int NORTH = 3;
    const int SOUTH = 4;

    #include "random.h"
    #include "DataHandler.h"
    #include "TreasureChest.h"

    using namespace adventure;

    RandomHandler randomBase;

    TreasureChest treasureChest;

    int main()
    {
    return 0;
    }

    //random.h

    #ifndef __random_h__

    #define __random_h__

    namespace adventure
    {
    const int NUMRANDOMS = 10000;

    //
    // RandomHandler class
    // used to store a bunch of randoms...used as a workaround
    //

    class RandomHandler
    {
    int randoms[NUMRANDOMS];
    int randomCounter;

    public:
    RandomHandler();
    int GetRandom();
    };

    }
    #endif


    //random.cpp
    #include "random.h"
    #include <stdlib.h>
    #include <time.h>


    namespace adventure
    {

    RandomHandler::RandomHandler()
    {
    int i;
    srand( (unsigned)time( NULL ) );

    for( i = 0; i < NUMRANDOMS; i++ )
    randoms = rand();

    randomCounter = 0;
    }

    int RandomHandler::GetRandom()
    {
    randomCounter++;
    if(randomCounter >= NUMRANDOMS)
    randomCounter = 0;

    return randoms[randomCounter];
    }
    }

    //DataHandler.h / DataHandler.cpp defines the class DataHandler
    //They work fine, however, so i excluded them...

    //TreasureChest.h
    #ifndef __TreasureChest_h__
    #define __TreasureChest_h__

    #include "DataHandler.h"

    namespace adventure
    {
    class DataHandler;
    class RandomHandler;

    //
    // Treasure struct.
    // Contains information about treasure.
    //
    struct Treasure {
    char name [50];
    int isWearable;
    int gold, hBonus, sBonus, aBonus;
    char type;
    int attackModifier, defenceModifier;
    };

    //
    // TreasureChest class
    // Manages treasures.
    //
    class TreasureChest
    {
    Treasure * treasures;
    Treasure emptyTreasure;
    int numTreasures;
    void AddTreasure(Treasure);
    void LoadTreasures();

    public:
    TreasureChest();
    Treasure GetTreasure(int);
    };
    }

    #endif

    //TreasureChest.cpp
    #include "TreasureChest.h"
    #include "DataHandler.h"
    #include <string.h>
    #include <stdlib.h>


    namespace adventure
    {

    const int TEXTMODE = 200;
    const int BINARYMODE = 201;

    TreasureChest::TreasureChest()
    {
    numTreasures = 0;
    treasures = new Treasure[1];
    strcpy(emptyTreasure.name, "No treasure");
    LoadTreasures();
    }

    void TreasureChest::AddTreasure(Treasure add)
    {

    treasures = (Treasure *) realloc(treasures, (numTreasures+1) *
    sizeof(Treasure));
    treasures[numTreasures] = add;
    numTreasures++;
    }

    void TreasureChest::LoadTreasures()
    {
    char input[100] = "";
    Treasure thisTreasure;
    DataHandler treasureGet ("treasure.txt",TEXTMODE);

    while(treasureGet.GetLine(input) != false) {
    if(input[0] != '#') {
    strcpy(thisTreasure.name,strtok(input, ";"));
    thisTreasure.isWearable = atoi(strtok(NULL, ";"));
    thisTreasure.type = atoi(strtok(NULL, ";"));
    thisTreasure.gold = atoi(strtok(NULL, ";"));
    thisTreasure.hBonus = atoi(strtok(NULL, ";"));
    thisTreasure.sBonus = atoi(strtok(NULL, ";"));
    thisTreasure.aBonus = atoi(strtok(NULL, ";"));
    thisTreasure.attackModifier = atoi(strtok(NULL, ";"));
    thisTreasure.defenceModifier = atoi(strtok(NULL, ";"));

    AddTreasure(thisTreasure);
    }
    }

    }

    Treasure TreasureChest::GetTreasure(int type)
    {
    int t;
    double r;

    do {
    r = ( (double) randomBase.GetRandom() / (double)(RAND_MAX+1) );
    //class instantiated in adventure.cpp - problem
    t = (int) (r * numTreasures);
    } while(treasures[t].type != type);
    return treasures[t];
    }

    }


    The compiler errors:
    --------------------Configuration: adventure - Win32
    Debug--------------------
    Compiling...
    TreasureChest.cpp
    d:\dokumenter\coding\adventure\treasurechest.cpp(60) : error C2065:
    'randomBase' : undeclared identifier
    d:\dokumenter\coding\adventure\treasurechest.cpp(60) : error C2228:
    left of '.GetRandom' must have class/struct/union type
    adventure.cpp
    DataHandler.cpp
    Error executing cl.exe.

    adventure.exe - 2 error(s), 0 warning(s)



    I put in comments where the errors are. Hope this helps... :)

    -Toke
    Toke H?iland-J?rgensen, Dec 31, 2003
    #7
  8. Toke H?iland-J?rgensen

    Ron Natalie Guest

    "Toke H?iland-J?rgensen" <> wrote in message news:...

    > #include <iostream.h>
    > #include <fstream.h>


    Get in the habit of using standard constructs. The include files are <iostream> and <fstream>.


    > const int WEAPON = 100;
    > const int ARMOR = 101;
    > const int CHARM = 102;
    > const int TEXTMODE = 200;
    > const int BINARYMODE = 201;
    > const int NUMRANDOMS = 10000;
    > const int EAST = 1;
    > const int WEST = 2;
    > const int NORTH = 3;
    > const int SOUTH = 4;


    You might consider grouping these into enums for convenience:
    enum Item { WEAPON, ARMOR, CHARM };
    enum Direction { EAST, WEST, NORTH, SOUTH } ; .
    etc..
    >
    > #ifndef __random_h__
    >
    > #define __random_h__


    Do not use symbols like this in your program. They are reserved for the compiler
    implementors.

    #ifndef INCLUDE_RANDOM_H
    #define INCLUDE_RANDOM_H

    > strcpy(thisTreasure.name,strtok(input, ";"));
    > thisTreasure.isWearable = atoi(strtok(NULL, ";"));


    strtok and atoi are both evil functions. atoi exhibits undefined behavior if
    you give it data outside the range. strtok is a piece of crap that has no
    business ever getting standardized. You do know that it writes over
    the input string (in addition to storing internal state).

    I'm not clear why you just didn't use a strea and formatted I/O here. It
    would have been much easier.

    > r = ( (double) randomBase.GetRandom() / (double)(RAND_MAX+1) );
    > //class instantiated in adventure.cpp - proble


    Because randomBase hasn't been seen in this file. You define it in main and there's no
    declaration for it elsewhere. You probably want to put
    extern RandomHandler randomBase
    in one of the include files.
    Ron Natalie, Dec 31, 2003
    #8
  9. Toke H?iland-J?rgensen

    Cy Edmunds Guest

    "Toke H?iland-J?rgensen" <> wrote in message
    news:...
    > "Victor Bazarov" <> wrote in message

    news:<EPqIb.11490$I07.23677@attbi_s53>...
    > > Most certainly, yes. However, don't attach it, copy-and-paste it.

    Also,
    > > remove all non-essential parts of the code and make sure that after that
    > > it still compiles with exactly the same error message as you claim it

    does.
    >
    > Okay...the program is an attempt at making a text adventure as an
    > excercise...
    >
    > //adventure.cpp
    > #include <iostream.h>
    > #include <stdlib.h>
    > #include <stdio.h>
    > #include <string.h>
    > #include <fstream.h>
    > #include <windows.h>
    >
    > const int WEAPON = 100;
    > const int ARMOR = 101;
    > const int CHARM = 102;
    > const int TEXTMODE = 200;
    > const int BINARYMODE = 201;
    > const int NUMRANDOMS = 10000;
    > const int EAST = 1;
    > const int WEST = 2;
    > const int NORTH = 3;
    > const int SOUTH = 4;
    >
    > #include "random.h"
    > #include "DataHandler.h"
    > #include "TreasureChest.h"
    >
    > using namespace adventure;
    >
    > RandomHandler randomBase;
    >
    > TreasureChest treasureChest;
    >
    > int main()
    > {
    > return 0;


    This looks like kind of a short adventure. :)

    > }
    >
    > //random.h
    >
    > #ifndef __random_h__
    >
    > #define __random_h__
    >
    > namespace adventure
    > {
    > const int NUMRANDOMS = 10000;
    >
    > //
    > // RandomHandler class
    > // used to store a bunch of randoms...used as a workaround
    > //
    >
    > class RandomHandler
    > {
    > int randoms[NUMRANDOMS];
    > int randomCounter;
    >
    > public:
    > RandomHandler();
    > int GetRandom();
    > };
    >
    > }
    > #endif
    >
    >
    > //random.cpp
    > #include "random.h"
    > #include <stdlib.h>
    > #include <time.h>
    >
    >
    > namespace adventure
    > {
    >
    > RandomHandler::RandomHandler()
    > {
    > int i;
    > srand( (unsigned)time( NULL ) );
    >
    > for( i = 0; i < NUMRANDOMS; i++ )
    > randoms = rand();
    >
    > randomCounter = 0;
    > }
    >
    > int RandomHandler::GetRandom()
    > {
    > randomCounter++;
    > if(randomCounter >= NUMRANDOMS)
    > randomCounter = 0;
    >
    > return randoms[randomCounter];
    > }
    > }
    >
    > //DataHandler.h / DataHandler.cpp defines the class DataHandler
    > //They work fine, however, so i excluded them...
    >
    > //TreasureChest.h
    > #ifndef __TreasureChest_h__
    > #define __TreasureChest_h__
    >
    > #include "DataHandler.h"
    >
    > namespace adventure
    > {
    > class DataHandler;
    > class RandomHandler;
    >
    > //
    > // Treasure struct.
    > // Contains information about treasure.
    > //
    > struct Treasure {
    > char name [50];
    > int isWearable;
    > int gold, hBonus, sBonus, aBonus;
    > char type;
    > int attackModifier, defenceModifier;
    > };
    >
    > //
    > // TreasureChest class
    > // Manages treasures.
    > //
    > class TreasureChest
    > {
    > Treasure * treasures;
    > Treasure emptyTreasure;
    > int numTreasures;
    > void AddTreasure(Treasure);
    > void LoadTreasures();
    >
    > public:
    > TreasureChest();
    > Treasure GetTreasure(int);
    > };
    > }
    >
    > #endif
    >
    > //TreasureChest.cpp
    > #include "TreasureChest.h"
    > #include "DataHandler.h"
    > #include <string.h>
    > #include <stdlib.h>
    >
    >
    > namespace adventure
    > {
    >
    > const int TEXTMODE = 200;
    > const int BINARYMODE = 201;
    >
    > TreasureChest::TreasureChest()
    > {
    > numTreasures = 0;
    > treasures = new Treasure[1];
    > strcpy(emptyTreasure.name, "No treasure");
    > LoadTreasures();
    > }
    >
    > void TreasureChest::AddTreasure(Treasure add)
    > {
    >
    > treasures = (Treasure *) realloc(treasures, (numTreasures+1) *
    > sizeof(Treasure));
    > treasures[numTreasures] = add;
    > numTreasures++;
    > }
    >
    > void TreasureChest::LoadTreasures()
    > {
    > char input[100] = "";
    > Treasure thisTreasure;
    > DataHandler treasureGet ("treasure.txt",TEXTMODE);
    >
    > while(treasureGet.GetLine(input) != false) {
    > if(input[0] != '#') {
    > strcpy(thisTreasure.name,strtok(input, ";"));
    > thisTreasure.isWearable = atoi(strtok(NULL, ";"));
    > thisTreasure.type = atoi(strtok(NULL, ";"));
    > thisTreasure.gold = atoi(strtok(NULL, ";"));
    > thisTreasure.hBonus = atoi(strtok(NULL, ";"));
    > thisTreasure.sBonus = atoi(strtok(NULL, ";"));
    > thisTreasure.aBonus = atoi(strtok(NULL, ";"));
    > thisTreasure.attackModifier = atoi(strtok(NULL, ";"));
    > thisTreasure.defenceModifier = atoi(strtok(NULL, ";"));
    >
    > AddTreasure(thisTreasure);
    > }
    > }
    >
    > }
    >
    > Treasure TreasureChest::GetTreasure(int type)
    > {
    > int t;
    > double r;
    >
    > do {
    > r = ( (double) randomBase.GetRandom() / (double)(RAND_MAX+1) );
    > //class instantiated in adventure.cpp - problem
    > t = (int) (r * numTreasures);
    > } while(treasures[t].type != type);
    > return treasures[t];
    > }
    >
    > }
    >
    >
    > The compiler errors:
    > --------------------Configuration: adventure - Win32
    > Debug--------------------
    > Compiling...
    > TreasureChest.cpp
    > d:\dokumenter\coding\adventure\treasurechest.cpp(60) : error C2065:
    > 'randomBase' : undeclared identifier
    > d:\dokumenter\coding\adventure\treasurechest.cpp(60) : error C2228:
    > left of '.GetRandom' must have class/struct/union type
    > adventure.cpp
    > DataHandler.cpp
    > Error executing cl.exe.
    >
    > adventure.exe - 2 error(s), 0 warning(s)
    >
    >
    >
    > I put in comments where the errors are. Hope this helps... :)
    >
    > -Toke


    OK, randomBase is a global variable defined in adventure.cpp. Then you try
    to use it in TreasureChest.cpp. Since that symbol isn't defined in that
    file, the compiler says, "undeclared identifier". That makes sense. The
    other error is spurious, trying to keep going without knowing what
    randomBase means.

    So how to fix it? You could declare randomBase external, but that would be a
    poor idea. I suggest you avoid global variables as much as possible. In this
    case I would suggest randomBase be declared in your main function and passed
    as an argument as needed; e.g.

    Treasure TreasureChest::GetTreasure(int type, RandomHandler &randomBase)

    --
    Cy
    http://home.rochester.rr.com/cyhome/
    Cy Edmunds, Dec 31, 2003
    #9
  10. "Cy Edmunds" <> wrote in message news:<SACIb.96774$>...
    > So how to fix it? You could declare randomBase external, but that would be a
    > poor idea. I suggest you avoid global variables as much as possible. In this
    > case I would suggest randomBase be declared in your main function and passed
    > as an argument as needed; e.g.
    >
    > Treasure TreasureChest::GetTreasure(int type, RandomHandler &randomBase)


    Ok, I will change my code to pass the global variables around as you
    suggested. It makes sense to do so instead of using global variables.
    Thanks alot for your help... :)

    -Toke
    Toke H?iland-J?rgensen, Jan 1, 2004
    #10
  11. "Ron Natalie" <> wrote in message news:<3ff2ebbc$0$66083$>...
    > strtok and atoi are both evil functions. atoi exhibits undefined behavior if
    > you give it data outside the range. strtok is a piece of crap that has no
    > business ever getting standardized. You do know that it writes over
    > the input string (in addition to storing internal state).
    >
    > I'm not clear why you just didn't use a strea and formatted I/O here. It
    > would have been much easier.
    >

    Thank you for your suggestions to improve my code.

    I'm afraid I don't know what 'strea and formatted I/O' is. I'd
    appreciate if you'd point me to a link describing it, or perhaps
    descibe it yourself... :)

    -Toke
    Toke H?iland-J?rgensen, Jan 1, 2004
    #11
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Victor Bazarov

    #include "file" -vs- #include <file>

    Victor Bazarov, Mar 5, 2005, in forum: C++
    Replies:
    4
    Views:
    523
    Exits Funnel
    Mar 6, 2005
  2. aurgathor
    Replies:
    1
    Views:
    305
  3. PTM
    Replies:
    1
    Views:
    317
    Andy Dingley
    Nov 12, 2007
  4. naveeddil
    Replies:
    0
    Views:
    550
    naveeddil
    Jan 4, 2008
  5. Andreas Bogenberger
    Replies:
    3
    Views:
    880
    Andreas Bogenberger
    Feb 22, 2008
Loading...

Share This Page