aJynks
aJynks

Reputation: 689

How do I split classes with inheritance up into different .h/.cpp files?

I have been working on a class and it is all big and ugly and would like to split each bit into its own cpp/.h files.

I can not seam to work out how to do this...

Here is my code http://ideone.com/n2Vjb

I understand that you place the class in the .h and the implementation in the .cpp... but I just can not get it to run, where it runs fine in a single file.

Upvotes: 1

Views: 1844

Answers (3)

JBentley
JBentley

Reputation: 6260

The following compiles and runs for me (albeit with a number of compiler warnings which you should probably look into):

file.h:

#ifndef FILE_H
#define FILE_H

#include <iostream>
#include <vector>
#include <algorithm>
#include <stdio.h>
#include <math.h>

using namespace std;

class MapFrames{
public:
        char frame[11];
        vector<short> cols;
        vector<short> rows;
        MapFrames (short a, short b);
};

class Cities : public MapFrames{
public:
        //Cords Holds map data. 0 = Unknown, 1 = City Location, 2 = Hit, 3 = Miss, 4 = Spy: Hit Nothing, 5 = Spy: Hit City
            vector<short>P1cords;
            vector<short>P2cords;
        Cities (short a, short b);
};

class PrintFuncs : public Cities{
public:
        PrintFuncs(short a, short b);
        void PrintTop();
        void PrintMid();
        void PrintBot();
        void PrintCords();
        void PrintGrid();
};

class GameBoard : PrintFuncs{
public:
        GameBoard (short a, short b);
        void display();
};

#endif

file.cpp:

#include "file.h"

MapFrames::MapFrames (short a, short b){
        // Construct a vector "rows" of a certain user defined size
        rows.resize(a);
        // Construct a vector "cols" of a certain user defined size
        cols.resize(b);
        //Construct Frames
        frame[0]=201; // Top LC
        frame[1]=205; // Horizontal
        frame[2]=187; // Top RC
        frame[3]=186; // Vertical
        frame[4]=200; // Bottom LC
        frame[5]=188; // Bottom RC

        //Construct Icons
        frame[6]=219;  // ICON: Hidden Locations 
        frame[7]=177;  // ICON: Spy Location: Nothing Found
        frame[8]=2;    // ICON: Spy Location: City Found
        frame[9]=127;  // ICON: Miss
        frame[10]=15;  // ICON: Destroyed City
}

Cities::Cities (short a, short b) : MapFrames (a,b){
    //Player 1 (LEFT)
        //Resize Vector to number of elements in map
        P1cords.resize(a*b);
        //set 1st 33% of elements (rounded up) to 1.
        for (int i=0; i<ceil((33/100.f)*(a*b)); i++){
                P1cords[i] = 1;
        }
        //Shuffle cords for random city locations.
        random_shuffle ( P1cords.begin(), P1cords.end() );

//Player 2 (RIGHT)
        //Resize Vector to number of elements in map
        P2cords.resize(a*b);
        //set 1st 33% of elements (rounded up) to 1.
        for (int i=0; i<ceil((33/100.f)*(a*b)); i++){
                P2cords[i] = 1;
        }
        //Shuffle cords for random city locations.
        random_shuffle ( P2cords.begin(), P2cords.end() );
}

PrintFuncs::PrintFuncs(short a, short b) : Cities (a,b){
}
void PrintFuncs::PrintTop(){
        cout<<frame[0]<<frame[1]<<frame[1]<<frame[1]<<frame[2];
}
void PrintFuncs::PrintMid(){
        cout<<frame[3]<<" "<<frame[6]<<" "<<frame[3];
}
void PrintFuncs::PrintBot(){
        cout<<frame[4]<<frame[1]<<frame[1]<<frame[1]<<frame[5];
}
void PrintFuncs::PrintCords(){
        cout<<"    ";
        for (int i=0; i<cols.size(); ++i){
                cout<<"  "<<i<<"  ";
        }
        cout<<"   ";
        for (int i=0; i<cols.size(); ++i){
                if (i+cols.size()<10){
                        cout<<"  "<<i+cols.size()<<"  ";}
                if (i+cols.size()>9){
                        cout<<"  "<<i+cols.size()<<" ";}
        }
        cout<<"\n";
}

void PrintFuncs::PrintGrid(){
        for (int j=0; j<rows.size(); ++j){
                //Print TopRow  
                cout<<"    ";
                for (int i=0; i<cols.size(); ++i){
                        PrintTop();
                }
                cout<<"   ";
                for (int i=0; i<cols.size(); ++i){
                        PrintTop();
                }
                cout<<"\n";
                //Print Middle Row
                cout<<"  "<<j<<" ";
                for (int i=0; i<cols.size(); ++i){
                        PrintMid();
                }
                cout<<"   ";
                for (int i=0; i<cols.size(); ++i){
                        PrintMid();
                }
                cout<<"\n";
                //Print Bottom Row
                cout<<"    ";
                for (int i=0; i<cols.size(); ++i){
                        PrintBot();
                }
                cout<<"   ";
                for (int i=0; i<cols.size(); ++i){
                        PrintBot();
                }
                cout<<"\n";
        }
}

GameBoard::GameBoard(short a, short b) : PrintFuncs (a,b){}
void GameBoard::display(){
        PrintCords();
        PrintGrid();
}

int main (){

        short rows = 0;short cols = 0;
        cout<<"Enter a value for ROWS - between 2-6: ";cin>>rows;
        cout<<"Enter a value for COLS - between 2-7: ";cin>>cols;
        cout<<endl<<endl;

//      short rows = 5;short cols = 5;
        GameBoard map(rows, cols);
        map.display();

        // End  
        std::cout<<std::endl<<std::endl<<std::endl<<"Please Close Console Window"<<std::endl;
        std::cin.ignore('\n', 1024);
        return(0);
}

In summary: includes, uses of namespaces and class declarations into the header file, and definitions in the source file. Include the header file at the top of the source file. The #ifndef, #define, and #endif ensure that the header file can only be included once, alternatively you can use #pragma once with most preprocessors. Also, as suggested by another answer, it would be neater to place each class into its own set of header/source files. This will have the added benefit that you won't need to worry about what order you list the class declarations: with the single-file approach, every class needs to be declared before it is used. In your case, that means that each declaration for a base class needs to appear before the inheriting class declaration.

Upvotes: 2

nutrina
nutrina

Reputation: 1042

Make sure you don't forget to put:

#include "HeaderFile.h"

in the cpp file, where "HeaderFile.h" is the name of the ".h" file containing the definition of the class you want to use in the cpp file.

If you have a file "MapFrames.h" containing:

#include <iostream>
#include <vector>
#include <algorithm>
#include <stdio.h>
#include <math.h>
using namespace std;

class MapFrames{
public:
    char frame[11];
    vector<short> cols;
    vector<short> rows;
    MapFrames (short a, short b);
};

then the cpp file "MapFrames.cpp" should contain:

#include "MapFrames.h"

MapFrames::MapFrames (short a, short b){
    // Construct a vector "rows" of a certain user defined size
    rows.resize(a);
    // Construct a vector "cols" of a certain user defined size
    cols.resize(b);
    //Construct Frames
    frame[0]=201; // Top LC
    frame[1]=205; // Horizontal
    frame[2]=187; // Top RC
    frame[3]=186; // Vertical
    frame[4]=200; // Bottom LC
    frame[5]=188; // Bottom RC

    //Construct Icons
    frame[6]=219;  // ICON: Hidden Locations 
    frame[7]=177;  // ICON: Spy Location: Nothing Found
    frame[8]=2;    // ICON: Spy Location: City Found
    frame[9]=127;  // ICON: Miss
    frame[10]=15;  // ICON: Destroyed City
}

Gerald

Upvotes: 2

stefan bachert
stefan bachert

Reputation: 9616

Put "class" into .h, at best one per class (interface)

class MapFrames{
public:
    char frame[11];
    vector<short> cols;
    vector<short> rows;
    MapFrames (short a, short b);
};

Put ...::... into .cpp (implementation)

MapFrames::MapFrames (short a, short b){
    // Construct a vector "rows" of 
...

Upvotes: 0

Related Questions