Defining many classes in a single file

A

Aguilar, James

I know that one can define an essentially unlimited number of classes in a
file. And one can declare just as many in a header file. However, the
question I have is, should I?

Suppose that, to use the common example, I have a situation where I am
implementing many types of Shapes. My current way of thinking is, well,
since they are all the same type, let's just put them all in the same file.
The include file would be "shapes.h" and it would contain not just the base
class Shape, but also Curve, Arc, Circle, Polygon, Quadrilateral, Rhombus,
Square, Octagon, Pentagon, etc.

I am in a situation where I would potentially be creating hundreds of
subclasses, most of which would inherit more than ninety percent of their
functionality from parent classes. However, I do not know of any design
alternative that would not require me to define all these various classes
and subclasses, since certain ones of the subclass would require some very
specialized behavior. Also, I intend that this system of "Shapes" would be
very extensible.

I had thought of busting out a .dat file and reading it during the
initialization phase of my program to describe the behavior of these
objects. However, I am inexperienced, to say the least, and I'm not sure a
scripting language to describe behavior is the best use of time on a project
that is pretty small.

So, I want to avoid an excessive number of source files, but I want a lot of
classes. Do I have the right solution?
 
S

Senapathy

Aguilar said:
I know that one can define an essentially unlimited number of classes in a
file. And one can declare just as many in a header file. However, the
question I have is, should I?

Suppose that, to use the common example, I have a situation where I am
implementing many types of Shapes. My current way of thinking is, well,
since they are all the same type, let's just put them all in the same file.
The include file would be "shapes.h" and it would contain not just the base
class Shape, but also Curve, Arc, Circle, Polygon, Quadrilateral, Rhombus,
Square, Octagon, Pentagon, etc.

I am in a situation where I would potentially be creating hundreds of
subclasses, most of which would inherit more than ninety percent of their
functionality from parent classes. However, I do not know of any design
alternative that would not require me to define all these various classes
and subclasses, since certain ones of the subclass would require some very
specialized behavior. Also, I intend that this system of "Shapes" would be
very extensible.

I had thought of busting out a .dat file and reading it during the
initialization phase of my program to describe the behavior of these
objects. However, I am inexperienced, to say the least, and I'm not sure a
scripting language to describe behavior is the best use of time on a project
that is pretty small.

So, I want to avoid an excessive number of source files, but I want a lot of
classes. Do I have the right solution?

My take on this subject (I don't know whether the experts would disagree!) :

About implementation files, I have my reservations about putting all the
classes' implementations into one file. You can easily split the
implementation into any number of files without sacrificing on end-user's
usability. The user of your classes can continue to include just 1 header
file of yours without needing to know which files they are implemented in.
If there are too many lines of code in 1 implementation file, it increases
the complexity of maintenance. Better to be modular.

Regarding header files, true that there is a convention that you should
declare only 1 class per header file. But there are precedences (doesn't
mean that they are necessarily right, but it just indicates that things are
not so drastically evil as it is made out to be, if you put multiple class
declarations in a header file)

I am giving a very platform specific example here. The MFC library has
numerous examples where a single header file declares many classes (if you
take a look at their collection classes, they are all declared in afxcoll.h,
numbering close to 20. Same is the case for the common control classes,
numbering nearly 20). Now the user has the convenience that he can include
just 1 header and start using multiple classes. If build time is a problem,
some compiler specific features could be there to reduce the build time.
(pre-compiled headers and pch files in VC++)

Senapathy
 
A

Aguilar, James

Senapathy said:

Followup question:

Won't having a whole bunch of different source files (say, put in a
subdirectory) be hell for the makefile? I can imagine a rule that says:

2dphysics.o: $(CCC) $(CFLAGS) ...(200 shape implementation files) shape.h

What do you do about that?
 
A

AVR



Followup question:

Won't having a whole bunch of different source files (say, put in a
subdirectory) be hell for the makefile? I can imagine a rule that says:

2dphysics.o: $(CCC) $(CFLAGS) ...(200 shape implementation files) shape.h

What do you do about that?

I work on a project with quite a lot of implementation files. What is
usually done for these kinds of projects is use autoconf/automake to
generate the makefile for you. Organize your files into appropriate
subdirectories (if you want) and create a Makefile.am in each,
specifying the library it constitutes, and the sources in the directory
that you want to link. Autoconf/automake will do the makefile generation
for you, depending on your configuration settings.
Moreover, writing one or two lines in the makefile for each file you
write does not seem to be too much of a burden from my POV, if that's
what you were implying. After all, you need to do it just once per file.

regards,
AVR
 
S

Senapathy

Aguilar said:
Senapathy said:

Followup question:

Won't having a whole bunch of different source files (say, put in a
subdirectory) be hell for the makefile? I can imagine a rule that says:

2dphysics.o: $(CCC) $(CFLAGS) ...(200 shape implementation files) shape.h

What do you do about that?

I suppose, you meant the linking part.
Each source (implementation) file would contribute to 1 object file each. So
the make file would contain some 200 lines for producing these 200 .o files.
Hmm... the _linker_ would need some 200 object files.

But I suppose the IDE should remove the complexity from the build procedure.
Even a batch mode should not be too much of a problem if you want to
automate the build procedure. Some IDEs provide a mechanism to export a make
file from the present source file / header file list.

I would still prefer factored implementations because of the maintenace
aspect. Ultimately that would matter more than the build procedure.
If you have some source control / configuration management scheme, all these
things would not matter at all. Source code readability, maintainability
would server you in good stead.

However, since you mentioned that there would be around 200 implementation
files, maintaining these files also would prove cumbersome.
So I guess you need to arrive at a logical grouping of these files and club
some implementations together. I have done it also under some circumstances,
so I can't say it is such a bad thing either :)

Senapathy
 
J

JKop

I routed through my old code and whipped out the following. Here's the
header file:


// pso.hpp

#ifndef INCLUDE_PHYSICALSHAPEOBJECT_HPP
#define INCLUDE_PHYSICALSHAPEOBJECT_HPP

#include <cmath>

namespace PSO{


typedef long double MeasurementBuffer;


class PhysicalShapeObject
{
public:
virtual MeasurementBuffer GetVolume(void) const = 0;
virtual MeasurementBuffer GetSurfaceArea(void) const = 0;
};



class Sphere : public PhysicalShapeObject
{
public:
MeasurementBuffer GetVolume(void) const
{

return (

( radius * radius * radius )

* 4.0

* 3.14 //Pie

/ 3.0

);


}

MeasurementBuffer GetSurfaceArea(void) const
{
return (

( radius * radius )

* 4.0

* 3.14 //Pie

);
}

protected:

MeasurementBuffer radius;
};



class Cylinder : public PhysicalShapeObject
{
public:

MeasurementBuffer GetVolume(void) const
{
return (

( radius * radius )

* height

* 3.14 //Pie


);
}

MeasurementBuffer GetSurfaceArea(void) const
{
//This includes the two ends of the cylinder

return (

( 2.0 * height + radius ) //Might be dodgy!

* radius

* 3.14 //Pie

);
}

protected:

MeasurementBuffer radius;
MeasurementBuffer height;
};


class Cone : public PhysicalShapeObject
{
public:

MeasurementBuffer GetVolume(void) const
{
return (

( radius * radius )

* height

* 3.14 //Pie

/ 3.0

);
}

MeasurementBuffer GetSurfaceArea(void) const
{
//This includes the end of the cone

return (


(

std::sqrt(
( radius * radius )

+ ( height * height )

)//END OF std::sqrt

+ ( radius )

)


* ( radius )

* 3.14

);
}

MeasurementBuffer GetLength(void) const
{
return (

std::sqrt(

( radius * radius )

+ ( height*height )

)//END OF std::sqrt

);
}

protected:

MeasurementBuffer radius;
MeasurementBuffer height;
};


class Block : public PhysicalShapeObject
{
public:

MeasurementBuffer GetVolume(void) const
{
return (

length * width * depth

);
}

MeasurementBuffer GetSurfaceArea(void) const
{
return (
2 * (

( length*width )

+ ( length * depth )

+ ( width * depth )

)

);
}

protected:

MeasurementBuffer length;
MeasurementBuffer width;
MeasurementBuffer depth;
};


} //END OF NAMESPACE


#endif //INCLUDE_PHYSICALSHAPEOBJECT_HPP




And there ain't no source file!


-JKop
 
G

Gernot Frisch

And there ain't no source file!

Yes, this is a very convenient method for small set's of classes that
do not get changed commonly. If however the file is quite huge or will
be changed commonly, you don't want to see the compilation times. I
use the Spirit++ parser generator (spirit.sf.net). It's a very huge
template library cosisting of headers only. Simple projects take very
long for compilation with it, although it's very convenient that you
only include a file and don't have to worry about any implementation
files.

-Gernot
 
D

Daniel T.

Aguilar said:
I know that one can define an essentially unlimited number of classes in a
file. And one can declare just as many in a header file. However, the
question I have is, should I?

Here is a simple rule: If class A depends on class B and B depends on A,
put them in the same header file. If A and only A depends on B, put them
in the same header file. Otherwise put the two classes in different
header files.
Suppose that, to use the common example, I have a situation where I am
implementing many types of Shapes. My current way of thinking is, well,
since they are all the same type, let's just put them all in the same file.
The include file would be "shapes.h" and it would contain not just the base
class Shape, but also Curve, Arc, Circle, Polygon, Quadrilateral, Rhombus,
Square, Octagon, Pentagon, etc.

Follow the rule above "If Curve depends on Shape and Shape depends on
Curve, put them in the same header file. If Curve and only Curve depends
on Shape, put them in the same header file. Otherwise put them in
different header files." Apply this rule to every combination of classes.

I am in a situation where I would potentially be creating hundreds of
subclasses, most of which would inherit more than ninety percent of their
functionality from parent classes. However, I do not know of any design
alternative that would not require me to define all these various classes
and subclasses, since certain ones of the subclass would require some very
specialized behavior. Also, I intend that this system of "Shapes" would be
very extensible.

I had thought of busting out a .dat file and reading it during the
initialization phase of my program to describe the behavior of these
objects. However, I am inexperienced, to say the least, and I'm not sure a
scripting language to describe behavior is the best use of time on a project
that is pretty small.

You seem to be contradicting yourself, on the one hand you say you
"would potentially be creating hundreds of subclasses" on the other you
say your working on a "project that is pretty small." Those two
statements don't connect well for me.
 
T

Thomas Matthews

I know that one can define an essentially unlimited number of classes in a
file. And one can declare just as many in a header file. However, the
question I have is, should I?

Suppose that, to use the common example, I have a situation where I am
implementing many types of Shapes. My current way of thinking is, well,
since they are all the same type, let's just put them all in the same file.
The include file would be "shapes.h" and it would contain not just the base
class Shape, but also Curve, Arc, Circle, Polygon, Quadrilateral, Rhombus,
Square, Octagon, Pentagon, etc.

I am in a situation where I would potentially be creating hundreds of
subclasses, most of which would inherit more than ninety percent of their
functionality from parent classes. However, I do not know of any design
alternative that would not require me to define all these various classes
and subclasses, since certain ones of the subclass would require some very
specialized behavior. Also, I intend that this system of "Shapes" would be
very extensible.

I had thought of busting out a .dat file and reading it during the
initialization phase of my program to describe the behavior of these
objects. However, I am inexperienced, to say the least, and I'm not sure a
scripting language to describe behavior is the best use of time on a project
that is pretty small.

So, I want to avoid an excessive number of source files, but I want a lot of
classes. Do I have the right solution?

I usually have one one class declared in a header file and
defined in a source file. I create directories / folders
to hold classes by theme. This helps with the maintenance
by having only one place to make one change. For example,
if I have class A & class B in a file, then if I change
class A, class B must also be recompiled. I like the
fact that I can get a class working, then not have to
recompile it due to changes in a non related class.

Another reason for one class one file is due to linker
resolution. Many Linkers have module scope as their
smallest resolution. If I have many classes defined
in a file and only want one, the linker will include
all the code for all the classes in that file (module
resolution). However, if I define only one class per
file, then I can only include the class I need and
not worry about extra code that I don't need.

In another thread, you ask about have many classes.
In this case, you can have libraries. Libraries are
collections of "object" files (the intermediary file
produced after compilation, but before linking).
This often speeds up the build process for classes
that don't change often. Many linkers support finer
resolution for library files than individual modules.
This may also alleviate symbol table overflow for
larger projects.

If you need multiple instances of classes at runtime
or the quantity varies at runtime, perhaps a factory
pattern is better suited. For example, one might
want a single Polygon class rather than pentagon,
hexagon, septagon and octagon classes. In this
case, you could create a hexagon instance by
specifying a 6 sided Polygon. All depends on your
project and your resources.

On the other hand, for small toy projects, I define
classes in one file until the quantity becomes
unwieldly. The effort and maintenance for multiple
files outweighs the time spent on the whole project.

--
Thomas Matthews

C++ newsgroup welcome message:
http://www.slack.net/~shiva/welcome.txt
C++ Faq: http://www.parashift.com/c++-faq-lite
C Faq: http://www.eskimo.com/~scs/c-faq/top.html
alt.comp.lang.learn.c-c++ faq:
http://www.raos.demon.uk/acllc-c++/faq.html
Other sites:
http://www.josuttis.com -- C++ STL Library book
 
M

Marcelo Pinto

Aguilar said:
Senapathy said:

Followup question:

Won't having a whole bunch of different source files (say, put in a
subdirectory) be hell for the makefile? I can imagine a rule that says:

2dphysics.o: $(CCC) $(CFLAGS) ...(200 shape implementation files) shape.h

What do you do about that?

[OT]
You don't have to make the dependencies explicitly (at least if you
are using gcc :)). consider the following makefile:

[makefile]
VPATH = OBJ:lib

..SUFFIXES:
..SUFFIXES: .cc .o

CC = gcc $(FLAG_COMPILATION)
AR = ar

LIB = libutil.a

OBJS = MiscProcs.o \
Cronometer.o

..cc.o:
@echo ">>>>>>>>>>> $<"
@$(CC) -c $<

all: $(LIB)
-@mv -f *.o OBJ 2>/dev/null
-@mv -f *.a lib 2>/dev/null

$(LIB): $(OBJS)
-@mv -f *.o OBJ 2>/dev/null
-@mv -f OBJ/*.o . 2>/dev/null
@sleep 1
-@rm -f $@
-@$(AR) r $@ $(OBJS)

include depend.mk

depend:
gcc -MM *.cc > depend.mk
clean:
-rm -f lib/$(LIB) core

clobber: clean
-rm -f *.o OBJ/*.o
-rm -f *.a lib/*.a
[/makefile]

After you manage to compile MiscProcs.cc and Cronometer.cc correctly,
you run "make depend" and the gcc will fill the file depend.mk with
the dependency information.

[/OT]

Good luck,

Marcelo Pinto
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top