tags:

views:

435

answers:

3

I'm using Visual Studio 2008 Express edition, and keep getting the following error:

"Cascadedisplay.h(4) : fatal error C1014: too many include files : depth = 1024.

Obviously I'm doing something very wrong with include files, but I just can't see what.

Basically, I have an interface class, StackDisplay, from which I want to derive CascadeDisplay in another file:

#if !defined __BASE_STACK_DISPLAY_H__
#define __BASE_STACK_DISPAY_H__

#include <boost\shared_ptr.hpp>
#include "CascadeDisplay.h"

namespace Sol
{
    class StackDisplay
    {
        public:
            virtual ~StackDisplay();
            static boost::shared_ptr<StackDisplay>
            make_cascade_display(boost::shared_ptr<int> csptr)
            {
                return boost::shared_ptr<StackDisplay>(new CascadeDisplay(csptr));
            }
    };
}
#endif

and then in CascadeDisplay.h:

#if !defined __CASCADE_DISPLAY_H__
#define __CASCADE_DISPAY_H__

#include "StackDisplay.h"
#include <boost\shared_ptr.hpp>

namespace Sol
{
    class CascadeDisplay: public StackDisplay
    {
        public:
            CascadeDisplay(boost::shared_ptr<int> csptr){};
    };
}

#endif

So what's up with that?

+3  A: 

Is #if !defined... legit? I always used #ifndef.

Either way, why does your "base" class require the reference to CascadeDisplay? That doesn't seem right. Consider replacing your call to create a new CascadeDisplay with a call to a pure virtual function in StackDisplay that your subclass must implement appropriately.

IE, something like (and forgive, I don't have a c++ compiler handy to check this):

namespace Sol
{
    class StackDisplay
    {
        public:
            virtual ~StackDisplay();
            boost::shared_ptr<StackDisplay>
            make_cascade_display(boost::shared_ptr<int> csptr)
            {
                return make_display(csptr);
            }

        protected:
            virtual boost::shared_ptr<StackDisplay> make_display(boost::shared_ptr<int> csptr) = 0;
    };

    class CascadeDisplay: public StackDisplay
    {
        public:
            CascadeDisplay(boost::shared_ptr<int> csptr){};

        protected:
            virtual boost::shared_ptr<StackDisplay> make_display(boost::shared_ptr<int> csptr)
            {
                return new CascadeDisplay(csptr);
            }
    };
}

I believe this solution is superior, in general, to the forward declaration because you're eliminating some tight coupling between your superclass and your subclass, and making a more generic interface besides. This lets you eliminate the #include of CascadeDisplay.h in StackDisplay.h.

Greg D
Greg, I have used your code and it compiles fine. I was using that reference to CascadeDisplay in the base class because of Item 31 in Effective C++. Scott Meyers did it, so I thought I would. Your solution is indeed superior however.
BeeBand
Having said that, your solution does not allow me to call `make_cascade_display()` on a `StackDisplay` pointer without making it a static function. If I do this, I get a complaint regarding the illegal call of the non-static `make_display()` from the static `make_cascade_display`.
BeeBand
Ah, I consider this to be part of the difficulty of conflating two roles in a single class. In general, I consider the "creation" of an object to be different from the "use" of an object, and so I typically prefer to create a separate factory class rather than use a factory method-- Especially in C++. A ghetto workaround to keep your method static might involve making a static settable property on StackDisplay that is a function pointer to the equivalent of the make_display method.
Greg D
+9  A: 
#if !defined __CASCADE_DISPLAY_H__
#define __CASCADE_DISPAY_H__

Second line should be:

#define __CASCADE_DISPLAY_H__

Same with:

#if !defined __BASE_STACK_DISPLAY_H__
#define __BASE_STACK_DISPAY_H__

Also, names that contain a double-underscore are reserved for the implementation, you are not allowed to create such names in your own code. Same goes for names that begin with a single underscore and an uppercase letter.

anon
@BeeBand: Use `#ifndef` to make typos like this visible. `#ifndef` is the same length as `#define`, so the macro names will be aligned, and you'll spot immediately that one is missing a character. :)
UncleBens
@UncleBens, good tip
BeeBand
+1 For the double underscore reserved for implementation.
Thomas Matthews
+4  A: 

There is a typo in your guards

#if !defined __CASCADE_DISPLAY_H__     <--- here you have DISPLAY
#define __CASCADE_DISPAY_H__           <--- here you have DISPAY (no L!)

and yes, avoid double underscores in such names

Krystian