Defining many classes in a single file

Discussion in 'C++' started by Aguilar, James, Jul 14, 2004.

  1. 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?
    Aguilar, James, Jul 14, 2004
    #1
    1. Advertising

  2. Aguilar, James

    Senapathy Guest

    "Aguilar, James" <> wrote in message
    news:cd2j3i$rk4$...
    > 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
    Senapathy, Jul 14, 2004
    #2
    1. Advertising

  3. "Senapathy" <> wrote in message
    news:cd2l4e$t0u$...
    >
    > [snip]


    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?
    Aguilar, James, Jul 14, 2004
    #3
  4. Aguilar, James

    AVR Guest

    Aguilar, James wrote:

    > "Senapathy" <> wrote in message
    > news:cd2l4e$t0u$...
    >
    >>[snip]

    >
    >
    > 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
    AVR, Jul 14, 2004
    #4
  5. Aguilar, James

    Senapathy Guest

    "Aguilar, James" <> wrote in message
    news:cd2m8j$sj8$...
    >
    > "Senapathy" <> wrote in message
    > news:cd2l4e$t0u$...
    > >
    > > [snip]

    >
    > 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
    Senapathy, Jul 14, 2004
    #5
  6. Aguilar, James

    JKop Guest

    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
    JKop, Jul 14, 2004
    #6
  7. > 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
    Gernot Frisch, Jul 14, 2004
    #7
  8. Aguilar, James

    Daniel T. Guest

    "Aguilar, James" <> wrote:

    >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.
    Daniel T., Jul 14, 2004
    #8
  9. Aguilar, James wrote:
    > 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
    Thomas Matthews, Jul 14, 2004
    #9
  10. "Aguilar, James" <> wrote in message news:<cd2m8j$sj8$>...
    > "Senapathy" <> wrote in message
    > news:cd2l4e$t0u$...
    > >
    > > [snip]

    >
    > 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
    Marcelo Pinto, Jul 14, 2004
    #10
    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. Henke

    Defining classes in jscript

    Henke, Nov 28, 2003, in forum: ASP .Net
    Replies:
    3
    Views:
    401
    Hans Kesting
    Nov 28, 2003
  2. johny smith
    Replies:
    8
    Views:
    400
    Peter Koch Larsen
    Jul 2, 2004
  3. Replies:
    8
    Views:
    1,344
    Victor Bazarov
    Jan 7, 2006
  4. Arun Kumar
    Replies:
    4
    Views:
    103
    Arun Kumar
    Oct 28, 2010
  5. vasudevram
    Replies:
    6
    Views:
    909
    vasudevram
    Apr 24, 2013
Loading...

Share This Page