C Board  

Go Back   C Board > General Programming Boards > C++ Programming

Reply
 
LinkBack Thread Tools Display Modes
Old 12-18-2008, 04:29 PM   #1
Registered User
 
Join Date: Oct 2006
Location: UK/Norway
Posts: 469
Class design problem

Hallo,

I am working on a program where I need to create a lot of different classes of almost the same type. But I am not sure how I should design the program so that it is easy to add a new class.

Here are the restrictions which makes it harder.
The classes has to work with the rest of the program (which is not written by me, and can not be change by me).

This is the base class which I can derive from in order to create a new class
Code:
class Man 
{
public:
	virtual void gatherInfo( /* a variable map */ ) = 0;
	virtual void doWork() = 0;
}
Right now I am doing this when I create new classes:
Code:
class IronWorker : public Man
{
	public:
		void gatherInfo( /* a variable map */ );
		void doWork();

	public:
		std::string m_name;
		int m_age;
		std::string m_workplace;

		std::string m_factoryName;
		std::string m_ironType;
}

class GarderWorker : public Man
{
	public:
		void gatherInfo( /* a variable map */ );
		void doWork();

	public:
		std::string m_name;
		int m_age;
		std::string m_workplace;

		std::string m_houseAdress;
		std::string m_floworNames[50];
		int m_kgDirtUsed;
}
When the program starts it goes into the gatherInfo() function of everyman and take the information in that map and stores it in the member variables. There are several variables that will be the same for every derived class (like name and age) but as of now I have to duplicate that code in every worker.

What I would like is to create classes more like this:
Code:
// A "new" base class
class Worker : public Man
{
public:
	void gatherInfo( /* a variable map */ );
	void doWork();

public:
	std::string m_name;
	int m_age;
	std::string m_workplace;
};

class IronWorker : public baseWorker
{
	public:
		void gatherInfo( /* a variable map */ );
		void doWork();

	public:
		std::string m_factoryName;
		std::string m_ironType;
}

class GarderWorker : public baseWorker
{
	public:
		void gatherInfo( /* a variable map */ );
		void doWork();

	public:
		std::string m_houseAdress;
		std::string m_floworNames[50];
		int m_kgDirtUsed;
}
In the code there the base variables will be gathered by the baseWorker class. But the gatherInfo function in baseWorker would never be called as it is a pure virtual function.

Any ideas on how to create a more user friendly way of doing this?
(The two virtual functions are the only two function that is called by the program)
h3ro is offline   Reply With Quote
Old 12-18-2008, 04:44 PM   #2
Registered User
 
C_ntua's Avatar
 
Join Date: Jun 2008
Posts: 1,285
I think you wanted to type this:
Code:
class baseWorker : public Man
I don't really see the problem of what you are doing.
The only "problem" seems that you won't call baseWorker gatherInfo and doWork functions ever.
So if you want to "fix" this just don't declare them. Do this:
Code:
class baseWorker : public Man
{
public:
	std::string m_name;
	int m_age;
	std::string m_workplace;
};
Note that baseWoker is also an abstract class. But that is OK with you, since you won't use it. I guess this is what you wanted.

Pure virtual functions have to be declared only once, making the class "valid" to use (not abstract anymore).

Other than that your idea is good and I don't see anything else to add
C_ntua is offline   Reply With Quote
Old 12-18-2008, 04:47 PM   #3
Registered User
 
Codeplug's Avatar
 
Join Date: Mar 2003
Posts: 3,903
>> But the gatherInfo function in baseWorker would never be called...
Just because it's virtual doesn't mean you can't be explicit in what you want to call. You can "chain" the virtual calls for example:
Code:
#include <iostream>
using namespace std;

struct base
{
    virtual void print_topdown() = 0 {cout << " base" << endl;}
    virtual void print_bottomup() = 0 {cout << " base" << endl;}
};//base

struct derived : public base
{
    virtual void print_topdown() 
    {
        cout << " derived" << endl;
        base::print_topdown();
    }
    
    virtual void print_bottomup() 
    {
        base::print_bottomup();
        cout << " derived" << endl;
    }
};//derived

struct further_derived : public derived
{
    virtual void print_topdown() 
    {
        cout << " further_derived" << endl;
        derived::print_topdown();
    }

    virtual void print_bottomup() 
    {
        derived::print_bottomup();
        cout << " further_derived" << endl;
    }
};//further_derived

int main()
{
    further_derived fd;
    base *b = &fd;
    cout << "Top-Down:" << endl;
    b->print_topdown();

    cout << "\nBottom-Up" << endl;
    b->print_bottomup();
    return 0;
}//main
gg
Codeplug is offline   Reply With Quote
Old 12-18-2008, 04:54 PM   #4
Registered User
 
Join Date: Oct 2006
Location: UK/Norway
Posts: 469
Codeplug: I did not know you could do that. It solved my problem perfectly! Thank you very very much
h3ro is offline   Reply With Quote
Old 12-18-2008, 05:10 PM   #5
The larch
 
Join Date: May 2006
Posts: 3,222
That doesn't compile, at least not with GCC or Comeau.

It appears that the implementation of pure virtual functions needs to be outside of the class:

Code:
struct base
{
    virtual void print_topdown() = 0;
    virtual void print_bottomup() = 0;
};//base

void base::print_topdown()
{
    cout << " base" << endl;
}

void base::print_bottomup()
{
    cout << " base" << endl;
}
__________________
I might be wrong.

Quote:
Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
Quoted more than 1000 times (I hope).
anon is offline   Reply With Quote
Old 12-18-2008, 05:14 PM   #6
Senior software engineer
 
brewbuck's Avatar
 
Join Date: Mar 2007
Location: Portland, OR
Posts: 5,768
Quote:
Originally Posted by anon View Post
That doesn't compile, at least not with GCC or Comeau.

It appears that the implementation of pure virtual functions needs to be outside of the class:
Why would you implement a pure virtual? That makes it not pure.
__________________
"Congratulations on your purchase. To begin using your quantum computer, set the power switch to both off and on simultaneously." -- raftpeople@slashdot
brewbuck is offline   Reply With Quote
Old 12-18-2008, 05:21 PM   #7
Registered User
 
Codeplug's Avatar
 
Join Date: Mar 2003
Posts: 3,903
Provide a default implementation, and enforce derive'ers to make their own. Never used it myself, but it seemed appropriate for the example since each derivation builds on the previous.

Good catch anon - MSVC blinded me

gg
Codeplug is offline   Reply With Quote
Old 12-18-2008, 05:29 PM   #8
The larch
 
Join Date: May 2006
Posts: 3,222
Quote:
Why would you implement a pure virtual? That makes it not pure.
I think what makes it "pure" is the = 0 tagged onto the prototype. You would at least have to agree that a pure virtual destructor has to have an implementation since all base classes will have their destructor called (perhaps this is your only option to make the class abstract, since no other method is a good candidate for being pure).
__________________
I might be wrong.

Quote:
Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
Quoted more than 1000 times (I hope).
anon is offline   Reply With Quote
Old 12-19-2008, 04:52 AM   #9
Mysterious C++ User
 
Elysia's Avatar
 
Join Date: Oct 2007
Posts: 14,787
Code:
class Man 
{
public:
	virtual void gatherInfo( /* a variable map */ ) = 0;
	virtual void doWork() = 0;
}
Code:
class IronWorker : public Man
{
	public:
		virtual void gatherInfo( /* a variable map */ );
		virtual void doWork();

	public:
		std::string m_name;
		int m_age;
		std::string m_workplace;

		std::string m_factoryName;
		std::string m_ironType;
}
Another note is that while the language does not enforce you to add "virtual" to function that is a inherited virtual function, it would be good practice, since anyone looking at that class would know it is indeed virtual without looking at the base class.
Further, all your member variables are public, exposed, which makes for poor abstraction. You really need to hide them.
__________________
Using: Microsoft Windows™ 7 Professional (x64), Microsoft Visual Studio™ 2008 Team System
I dedicated my life to helping others. This is only a small sample of what they said:
"Thanks Elysia. You're a programming master! How the hell do you know every thing?"
Quoted... at least once.
Quote:
Originally Posted by cpjust
If C++ is 2 steps forward from C, then I'd say Java is 1 step forward and 2 steps back.
Elysia is online now   Reply With Quote
Old 12-19-2008, 08:26 AM   #10
Registered User
 
C_ntua's Avatar
 
Join Date: Jun 2008
Posts: 1,285
Yeah, I wanted to mention that earlier but I forgot. Since the gatherInfo(), as you say, will get information and store them and the doWork() will do the job, probably you want all the variables private. You might want another function, like printInfo() to print the variables.
C_ntua is offline   Reply With Quote
Old 12-19-2008, 09:10 AM   #11
Registered User
 
Join Date: Oct 2006
Location: UK/Norway
Posts: 469
In my real program they are private. The worker classes was just something that I created as an example.
h3ro is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Getting an error with OpenGL: collect2: ld returned 1 exit status Lorgon Jortle C++ Programming 6 05-08-2009 08:18 PM
which design is better to wrap another class instance George2 C++ Programming 7 04-13-2008 12:27 AM
singleton class problem ... C++ Programming 6 12-22-2003 06:16 PM
Quaternion class problem Lurker C++ Programming 14 11-18-2003 06:01 PM
static class problem. Sebastiani C++ Programming 3 10-16-2002 03:27 PM


All times are GMT -6. The time now is 07:07 AM.


Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.3.2

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22