Solved

Confused with C++ header files

Posted on 2012-03-12
5
281 Views
Last Modified: 2012-03-12
Ok I've got a c++ project that I want to break down into properly organized header files but the help has me confused
Here is an example i found on the internet:


Date.h:
	
#ifndef DATE_H
#define DATE_H
 
class Date
{
private:
    int m_nMonth;
    int m_nDay;
    int m_nYear;
 
    Date() { } // private default constructor
 
public:
    Date(int nMonth, int nDay, int nYear);
 
    void SetDate(int nMonth, int nDay, int nYear);
 
    int GetMonth() { return m_nMonth; }
    int GetDay()  { return m_nDay; }
    int GetYear() { return m_nYear; }
};
 
#endif

Open in new window

Date.cpp:
	
#include "Date.h"
 
// Date constructor
Date::Date(int nMonth, int nDay, int nYear)
{
    SetDate(nMonth, nDay, nYear);
}
 
// Date member function
void Date::SetDate(int nMonth, int nDay, int nYear)
{
    m_nMonth = nMonth;
    m_nDay = nDay;
    m_nYear = nYear;
}

Open in new window


Ok my issue here is that there is actual code in the header file! but only for the accessors ...  not for the constructor.  Seems inconsistent to me so I'm not sure how I should be fixing my own code (Which will not compile as is due to lack of forward declaration.)
0
Comment
Question by:GPicasso
  • 3
5 Comments
 
LVL 86

Expert Comment

by:jkr
ID: 37712292
Can you post your code? That'd be much easier and more efficient ;o)
0
 

Author Comment

by:GPicasso
ID: 37712338
#include <stack>
#include <vector>
#include <string>
#include <queue>
#include <iostream>

using namespace std;

#define NUMBER_OF_PROCESSORS 8
#define MAX_JOBS 2


class Processor
/* This class represents processors                 *
 * it includes a processor ID but it's not          *
 * yet important                                    *
 *                                                 */
{
private:
    int processorID_;        // This is a unique integet to tell one processor 
                             // from the next
    string type_;  //This tells what type of processor 
                                          // is attached to the object
public:
    Processor()
    {
        processorID_ = 0;
        type_ =  "GenuineMakeBelieve";
        // this is all just examples we could put all kinds of stuff
        // in here to tie this to a real processor and get statistics 
        // or even have affinity for some jobs to certian types of processors
        // but this is all make believe anyhow
    }
    int getID()
    /* This should return the processor ID*/
    {
        return processorID_;
    }
    string getType()
    /*This should return a string identifying the sort of processor
     */
    {
        return type_;
    }
    
};
class System
/* This class represents the system it's for storing the state of anything
 * that doesn't clearly belong in some other class
 * right now it only stores the free processor pool and the current next 
 * process ID
 */
{
private:

    int nextPid;
    vector<Processor> freePool_;
public:
    System()
    {   
        freePool_ = new vector<Processor>;
        nextPid = 0;
        
    }
    int getPID()   /// static int getPID() ???
    /*This allocates and returns the next available process ID*/
    {
        return ++nextPid; 
    }
    Processor getProcessor()
    /* This method gets a free processor from the system*/
    {
        Processor r = freePool_.back();
        freePool_.pop_back();
        return r;
    }
    void takeProcessor(Processor processor)
    /* This method gives the processor back to the system*/
    {
        freePool_.push_back(processor);
    }
   
};


class Job
/* The job class represents an actual job with a name
 * a stack of captured processors a list of ticks and a PID for the job*/
{
private:
    vector<Processor> captiveProcessors_;
    string name_;
    int PID_;
    int ticksRemaining_;
public:
    Job(string name, int processors, int ticks)
    {
        name_ = name;
        ticksRemaining_ = ticks;
        PID_ = system_.getPID();
    }
    void takeProcessor(Processor processor)
    /*This takes a processor and makes it captive*/
    {
        captiveProcessors_.push_back(processor);
    }
    void tick()
    /*decrement the ticks and return ticks remaining*/
    {
        return --ticksRemaining_;
    }
    
    
    bool operator>= (Job &job1, Job &job2)
    {
        return job1.ticksRemaining_ >= job2.ticksRemaining_;
    }
    bool operator<= (Job &job1, Job &job2)
    {
        return job1.ticksRemaining_ <= job2.ticksRemaining_;
    }
    bool operator== (Job &job1, Job &job2)
    {
        return job1.ticksRemaining_ == job2.ticksRemaining_;
    }
    bool operator!= (Job &job1, Job &job2)
    {
        return job1.ticksRemaining_ != job2.ticksRemaining_;
    }
    friend ostream &operator<<(ostream& out,const Job& job)
    {
        out <<job.name_ + "\t" job.PID_ + + "\t" + job.ticksRemaining_ + "\t\n";
        return out;
    }
};

class Scheduler
/* This class represents a scheduler object
 What should happen here is the user should be able to submit
 * a job request (sendjobrequest). it should get enqueud in a regular queue and
 *  at each tick it will 
 * convert those requests into 
 */
{ 
private:
    vector<Job> runQueue_;  //  This is the queue that running jobs sit in
    vector<Job> waitQueue_; //  This is the queue that not running jobs sit in
    void tickRunQueue()
    /*private method to manipulate the runQueue*/
    {
        for (int i=0; i<=runQueue_.size();i++)
        {
           if (0 >= runQueue_.at(i).tick())
           /* if there are no ticks left anyhow then free the memory and remove 
            the pointer from the Queue*/
           {
               delete(runQueue_.back());
               runQueue_.pop_back();
           }
           
           cout << runQueue_.at(i);
        }
    }
    void tickWaitQueue()
    /* private method to move a */
    {
        runQueue_.push_back(waitQueue_.back());
        waitQueue_.pop_back();
    }
   
public:
    Scheduler()
    {
        runQueue_ = new vector<Job>();
        waitQueue_ = new vector<Job>();
    }
    processJobRequest(JobRequest jobRequest)
    /* This converts a job request into an actual job
       This is where jobRequests go to die*/
    {
        waitQueue_.push_back(new Job(jobRequest.getName(), jobRequest.getProcessingRequirements(),jobRequest.getTicksRequired()));
        delete(jobRequest);
    }
    tick()
    {
        // I would make a queue that you can put new submissions to and a threaded
        // shell.. but I looked at pthreads,, no that's not going to happen, and 
        // honestly I don't know any other sensible way to allow users to submit
        // a job during any tick.. but here are some comments
        // if (submissionqueue) {pop the thing off the queue and processoJobRequest()
        // good enough  
        // I take that back maybe I'll use kbhit() to get some text input if I have time
        // forget it I don't even have the curses libraries installed.. no interactive shell
    
        // if queue is not empty and enough processors are available then pop
        // a job off and give it processors     
        
    }
    
};






class JobRequest
/*  This represents a request to create a job it had yet to actually
 * move on to that point in it's lifecycle.. note the lack of PID
*/
{
private:
    string name_;
    int numberOfProcessors_;
    int numberOfTicks_;
public:
    JobRequest(string name, int numberOfProcessors, int numberOfTicks)
    {
       name_ = name_;
       numberOfProcessors_ = numberOfProcessors;
       numberOfTicks_ = numberOfTicks;
    }
    string getName()
    /*returns the name of the job, exmple: ls, pwd, javac*/
    {
        return name_;
    }
    int getProcessingRequirements()
    /*returns the number of processors required to run this job*/
    {
        return numberOfProcessors_;
    }
    int getTicksRequired()
    /* Returns the number of ticks this program is going to consume*/
    {
        return numberOfTicks_;
    }
};

System system_; // this simulates system features normally outside of the scheduler

int main()
{
    // System objects, scheduler and system get created here
    // Processors get created too
 
    system_ = new System();
    Scheduler scheduler = new Scheduler();
    
    /*make the processors*/
    for (int i = 0; i < NUMBER_OF_PROCESSORS; i++)
    {
        system_.takeProcessor(new Processor());
    }
    
    scheduler.processJobRequest(new JobRequest("nethack", 2, 4));
    scheduler.processJobRequest(new JobRequest("gcc", 4, 2));
    scheduler.processJobRequest(new JobRequest("pwd", 7, 3));
    scheduler.processJobRequest(new JobRequest("javac", 3, 8));
    scheduler.processJobRequest(new JobRequest("clear", 3, 3));
    scheduler.processJobRequest(new JobRequest("fortune", 1, 1));
            
    
    scheduler.processJobRequest(new JobRequest("nethack", 2, 4));
    scheduler.processJobRequest(new JobRequest("gcc", 4, 2));
    scheduler.processJobRequest(new JobRequest("pwd", 7, 3));
    scheduler.processJobRequest(new JobRequest("javac", 3, 8));
    scheduler.processJobRequest(new JobRequest("clear", 3, 3));
    scheduler.processJobRequest(new JobRequest("fortune", 1, 1));
            
    
    scheduler.processJobRequest(new JobRequest("nethack", 2, 4));
    scheduler.processJobRequest(new JobRequest("gcc", 4, 2));
    scheduler.processJobRequest(new JobRequest("pwd", 7, 3));
    scheduler.processJobRequest(new JobRequest("javac", 3, 8));
    scheduler.processJobRequest(new JobRequest("clear", 3, 3));
    scheduler.processJobRequest(new JobRequest("fortune", 1, 1));
            
    
    scheduler.processJobRequest(new JobRequest("nethack", 2, 4));
    scheduler.processJobRequest(new JobRequest("gcc", 4, 2));
    scheduler.processJobRequest(new JobRequest("pwd", 7, 3));
    scheduler.processJobRequest(new JobRequest("javac", 3, 8));
    scheduler.processJobRequest(new JobRequest("clear", 3, 3));
    scheduler.processJobRequest(new JobRequest("fortune", 1, 1));
    
    while(1)
    {
        scheduler.tick();
    }
            
    
}

Open in new window


As you can see I junked it up quite a bit moving things around and then realized putting all this into a properly structured c++ project with headers for all the classes would fix a lot of my issues which seemed to be forward declaration related.

But the code is here enough that I think a good C++ programmer could visualize the way it should be.

There are other problems I'm sure and maybe even some missing code but I can't take this any further until I've done some re-organizing.
0
 
LVL 86

Accepted Solution

by:
jkr earned 500 total points
ID: 37712393
Err, a foward declaration for sure was not your problem - see the comments in the corrected code ;o)

#include <stack>
#include <vector>
#include <string>
#include <queue>
#include <iostream>

using namespace std;

#define NUMBER_OF_PROCESSORS 8
#define MAX_JOBS 2

class JobRequest
/*  This represents a request to create a job it had yet to actually
 * move on to that point in it's lifecycle.. note the lack of PID
*/
{
private:
    string name_;
    int numberOfProcessors_;
    int numberOfTicks_;
public:
    JobRequest(string name, int numberOfProcessors, int numberOfTicks)
    {
       name_ = name_;
       numberOfProcessors_ = numberOfProcessors;
       numberOfTicks_ = numberOfTicks;
    }
    string getName()
    /*returns the name of the job, exmple: ls, pwd, javac*/
    {
        return name_;
    }
    int getProcessingRequirements()
    /*returns the number of processors required to run this job*/
    {
        return numberOfProcessors_;
    }
    int getTicksRequired()
    /* Returns the number of ticks this program is going to consume*/
    {
        return numberOfTicks_;
    }
};


class Processor
/* This class represents processors                 *
 * it includes a processor ID but it's not          *
 * yet important                                    *
 *                                                 */
{
private:
    int processorID_;        // This is a unique integet to tell one processor 
                             // from the next
    string type_;  //This tells what type of processor 
                                          // is attached to the object
public:
    Processor()
    {
        processorID_ = 0;
        type_ =  "GenuineMakeBelieve";
        // this is all just examples we could put all kinds of stuff
        // in here to tie this to a real processor and get statistics 
        // or even have affinity for some jobs to certian types of processors
        // but this is all make believe anyhow
    }
    int getID()
    /* This should return the processor ID*/
    {
        return processorID_;
    }
    string getType()
    /*This should return a string identifying the sort of processor
     */
    {
        return type_;
    }
    
};
class System
/* This class represents the system it's for storing the state of anything
 * that doesn't clearly belong in some other class
 * right now it only stores the free processor pool and the current next 
 * process ID
 */
{
private:

    int nextPid;
    vector<Processor> freePool_;
public:
    System()
    {   
        //freePool_ = new vector<Processor>; this is not needed at all, 'freePool_' is not a pointer
        nextPid = 0;
        
    }
    int getPID()   /// static int getPID() ???
    /*This allocates and returns the next available process ID*/
    {
        return ++nextPid; 
    }
    Processor getProcessor()
    /* This method gets a free processor from the system*/
    {
        Processor r = freePool_.back();
        freePool_.pop_back();
        return r;
    }
    void takeProcessor(Processor processor)
    /* This method gives the processor back to the system*/
    {
        freePool_.push_back(processor);
    }
   
};

// needs to be 'known' earlier
System system_; // this simulates system features normally outside of the scheduler


// binary operators need to be global

class Job;

    bool operator>= (Job &job1, Job &job2);
    bool operator<= (Job &job1, Job &job2);
    bool operator== (Job &job1, Job &job2);
    bool operator!= (Job &job1, Job &job2);
    ostream &operator<<(ostream& out,const Job& job);


class Job
/* The job class represents an actual job with a name
 * a stack of captured processors a list of ticks and a PID for the job*/
{

    friend bool operator>= (Job &job1, Job &job2);
    friend bool operator<= (Job &job1, Job &job2);
    friend bool operator== (Job &job1, Job &job2);
    friend bool operator!= (Job &job1, Job &job2);
    friend ostream &operator<<(ostream& out,const Job& job);


private:
    vector<Processor> captiveProcessors_;
    string name_;
    int PID_;
    int ticksRemaining_;
public:
    Job(string name, int processors, int ticks)
    {
        name_ = name;
        ticksRemaining_ = ticks;
        PID_ = system_.getPID();
    }
    void takeProcessor(Processor processor)
    /*This takes a processor and makes it captive*/
    {
        captiveProcessors_.push_back(processor);
    }
    int tick() // needs to be non-void to return something
    /*decrement the ticks and return ticks remaining*/
    {
        return --ticksRemaining_;
    }
    
    
};

    bool operator>= (Job &job1, Job &job2)
    {
        return job1.ticksRemaining_ >= job2.ticksRemaining_;
    }
    bool operator<= (Job &job1, Job &job2)
    {
        return job1.ticksRemaining_ <= job2.ticksRemaining_;
    }
    bool operator== (Job &job1, Job &job2)
    {
        return job1.ticksRemaining_ == job2.ticksRemaining_;
    }
    bool operator!= (Job &job1, Job &job2)
    {
        return job1.ticksRemaining_ != job2.ticksRemaining_;
    }
    ostream &operator<<(ostream& out,const Job& job)
    {
        out <<job.name_ << "\t" << job.PID_ << "\t" << job.ticksRemaining_ << "\t\n"; // no +, just <<
        return out;
    }

class Scheduler
/* This class represents a scheduler object
 What should happen here is the user should be able to submit
 * a job request (sendjobrequest). it should get enqueud in a regular queue and
 *  at each tick it will 
 * convert those requests into 
 */
{ 
private:
    vector<Job> runQueue_;  //  This is the queue that running jobs sit in
    vector<Job> waitQueue_; //  This is the queue that not running jobs sit in
    void tickRunQueue()
    /*private method to manipulate the runQueue*/
    {
        for (int i=0; i<=runQueue_.size();i++)
        {
           if (0 >= runQueue_.at(i).tick())
           /* if there are no ticks left anyhow then free the memory and remove 
            the pointer from the Queue*/
           {
               //delete(runQueue_.back()); that's completely off, sorry...
               runQueue_.pop_back();
           }
           
           cout << runQueue_.at(i);
        }
    }
    void tickWaitQueue()
    /* private method to move a */
    {
        runQueue_.push_back(waitQueue_.back());
        waitQueue_.pop_back();
    }
   
public:
    Scheduler()
    {
        //runQueue_ = new vector<Job>(); both aren't pointers!
        //waitQueue_ = new vector<Job>();
    }
    void processJobRequest(JobRequest jobRequest) // need some return type
    /* This converts a job request into an actual job
       This is where jobRequests go to die*/
    {
        waitQueue_.push_back(Job(jobRequest.getName(), jobRequest.getProcessingRequirements(),jobRequest.getTicksRequired())); // still not a pointer!
        //delete(jobRequest); ???
    }
    void tick()
    {
        // I would make a queue that you can put new submissions to and a threaded
        // shell.. but I looked at pthreads,, no that's not going to happen, and 
        // honestly I don't know any other sensible way to allow users to submit
        // a job during any tick.. but here are some comments
        // if (submissionqueue) {pop the thing off the queue and processoJobRequest()
        // good enough  
        // I take that back maybe I'll use kbhit() to get some text input if I have time
        // forget it I don't even have the curses libraries installed.. no interactive shell
    
        // if queue is not empty and enough processors are available then pop
        // a job off and give it processors     
        
    }
    
};


int main()
{
    // System objects, scheduler and system get created here
    // Processors get created too
 
    //system_ = new System(); not a pointer and declared earlier
    Scheduler scheduler;// = new Scheduler(); not a pointer
    
    /*make the processors*/
    for (int i = 0; i < NUMBER_OF_PROCESSORS; i++)
    {
        system_.takeProcessor(Processor()); // still no pointers involved
    }
    
    scheduler.processJobRequest(JobRequest("nethack", 2, 4));
    scheduler.processJobRequest(JobRequest("gcc", 4, 2));
    scheduler.processJobRequest(JobRequest("pwd", 7, 3));
    scheduler.processJobRequest(JobRequest("javac", 3, 8));
    scheduler.processJobRequest(JobRequest("clear", 3, 3));
    scheduler.processJobRequest(JobRequest("fortune", 1, 1));
            
    
    scheduler.processJobRequest(JobRequest("nethack", 2, 4));
    scheduler.processJobRequest(JobRequest("gcc", 4, 2));
    scheduler.processJobRequest(JobRequest("pwd", 7, 3));
    scheduler.processJobRequest(JobRequest("javac", 3, 8));
    scheduler.processJobRequest(JobRequest("clear", 3, 3));
    scheduler.processJobRequest(JobRequest("fortune", 1, 1));
            
    
    scheduler.processJobRequest(JobRequest("nethack", 2, 4));
    scheduler.processJobRequest(JobRequest("gcc", 4, 2));
    scheduler.processJobRequest(JobRequest("pwd", 7, 3));
    scheduler.processJobRequest(JobRequest("javac", 3, 8));
    scheduler.processJobRequest(JobRequest("clear", 3, 3));
    scheduler.processJobRequest(JobRequest("fortune", 1, 1));
            
    
    scheduler.processJobRequest(JobRequest("nethack", 2, 4));
    scheduler.processJobRequest(JobRequest("gcc", 4, 2));
    scheduler.processJobRequest(JobRequest("pwd", 7, 3));
    scheduler.processJobRequest(JobRequest("javac", 3, 8));
    scheduler.processJobRequest(JobRequest("clear", 3, 3));
    scheduler.processJobRequest(JobRequest("fortune", 1, 1));
    
    while(1)
    {
        scheduler.tick();
    }
            
    
}
                                            

Open in new window

0
 
LVL 28

Expert Comment

by:pepr
ID: 37712491
>> Ok my issue here is that there is actual code in the header file! but only for the accessors ...  not for the constructor.

Notice the line 15 in your header
Date(int nMonth, int nDay, int nYear);

Open in new window


This is the constructor.  Only the default constructor is made private to prevent the situation when anyone tries to create "uninitialized" object in the sense of its functionality.  In other words, the date object must be given some date when created.  It cannot be postponed.  The implementation of the constructor (its body) is located at the .cpp file.  The compiler actually compiles the .cpp files.  The .h files are included as text by the #include directive.  The result is the same as if you copied it to that place.

The accessor GetMonth() etc should actually be made inlines to make the code possibly more efficient.
0
 
LVL 86

Expert Comment

by:jkr
ID: 37712511
pepr, try to compile his original code - that was not an issue.
0

Featured Post

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

Before You Read The Article Please make sure you understand these two concepts: Variable Scope (http://www.php.net/manual/en/language.variables.scope.php) and Property Visibility (http://www.php.net/manual/en/language.oop5.visibility.php).  And to …
The Fluent Interface Design Pattern You can use the Fluent Interface (http://en.wikipedia.org/wiki/Fluent_interface) design pattern to make your PHP code easier to read and maintain.  "Fluent Interface" is an object-oriented design pattern that r…
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

707 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now