How can I forward declare a struct/custom type in my include? I'm trying to write an include but it keeps telling me incomplete type or type not declared..


I do not have a .CPP to go with it.. I wrote everything in here as I have never written an include before. The problem is at line 57, MidPointBox. Also Am I supposed to use templates?

Types.h

#ifndef TYPES_H_INCLUDED
#define TYPES_H_INCLUDED
#include <math.h>


/** Definitions **/
#define LEN(a) (sizeof(a)/sizeof(*a))
#define HIGH(a) (sizeof(a)/sizeof(*a) - 1)

#define Repeat do{
#define Until(condition) }while(!(condition));


/** Types **/

struct Box;

struct Point
{
    int X, Y;
    Point() {X = Y = 0;};                              //Default constructor.
    Point(int X_, int Y_) : X(X_), Y(Y_) {};           //Alternate constructor.
    ~Point(){};                                        //Destructor.

    int operator == (const Point &PT) const            //Are the points Equal?
    {
        return ((X == PT.X) && (Y == PT.Y));
    }

    int operator != (const Point &PT) const            //Are the points Not equal?
    {
        return ((X != PT.X) && (Y != PT.Y));
    }

    Point& operator = (const Point& PT)
    {
        if (this != &PT)
        {
            X = PT.X;
            Y = PT.Y;
        }
        return *this;
    }

    Point operator += (Point PT)
    {
        X += PT.X;
        Y += PT.Y;
        return *this;
    }

    Point operator -= (Point PT)
    {
        X -= PT.X;
        Y -= PT.Y;
        return *this;
    }

    Point MidPointBox (Box B)
    {
        int MX = ((B.X1 + B.Y1)/2);
        int MY = ((B.X2 + B.Y2)/2);

        return Point(MX, MY);
    }

    friend inline Point operator+(Point P1, Point P2)           //Add two points.
    {
        return Point(P1.X + P2.X, P1.Y + P2.Y);
    }

    friend inline Point operator-(Point P1, Point P2)           //Subtract two points.
    {
        return Point(P1.X - P2.X, P1.Y - P2.Y);                 //No absolute value needed since points can have negative values.
    }

    friend inline int Distance(Point P1, Point P2)              //Friend is for Inheritance and friendship of a Class/Struct.
    {
        return (hypot(P1.X - P2.X, P1.Y - P2.Y));
    }

    friend inline Point Invert(Point PT)                     //Invert a point.
    {
        return Point(-PT.X, -PT.Y);
    }
};

struct Box
{
    int X1, Y1, X2, Y2;
    Box(){X1 = Y1 = X2 = Y2 = 0;};                                                      //Default Constructor.
    Box(int X1_, int Y1_, int X2_, int Y2_) : X1(X1_), Y1(Y1_), X2(X2_), Y2(Y2_) {};    //Alternate Constructor.
    ~Box(){};                                                                           //Destructor.

    int operator == (const Box &B) const                                                //Are the Boxes the same?
    {
        return ((X1 == B.X1) && (X2 == B.X2) && (Y1 == B.Y1) && (Y2 == B.Y2));
    }

    int operator != (const Box &B) const                                                //Are the Boxes Not the same?
    {
        return ((X1 != B.X1) && (X2 != B.X2) && (Y1 != B.Y1) && (Y2 != B.Y2));
    }

    Box operator += (Box B)
    {
        X1 += B.X1;
        Y1 += B.Y1;
        X2 += B.X2;
        Y2 += B.Y2;
        return *this;
    }

    Box operator -= (Box B)
    {
        X1 -= B.X1;
        Y1 -= B.Y1;
        X2 -= B.X2;
        Y2 -= B.Y2;
        return *this;
    }

    Box PointToBox (Point UpperLeft, Point LowerRight)
    {
        return Box(UpperLeft.X, UpperLeft.Y, LowerRight.X, LowerRight.Y);
    }

    Box& operator = (const Box& B)
    {
        if (this != &B)
        {
            X1 = B.X1;
            Y1 = B.Y1;
            X2 = B.X2;
            Y2 = B.Y2;
        }
        return *this;
    }

    friend inline Box operator + (Box B1, int S)                                              //Increase Box Size.
    {
        return Box(B1.X1 + S, B1.Y1 + S, B1.X2 + S, B1.Y2 + S);
    }

    friend inline Box operator - (Box B1, int S)                                              //Decrease Box Size.
    {
        if (((B1.X1 - S) < 0) || ((B1.Y1 - S) < 0) || ((B1.X2 - S) < 0) || ((B1.Y2 - S) < 0))
            return Box(-1, -1, -1, -1);                                                     //Return -1's if its not a valid box.
        else if (((B1.X1 - S) == 0) || ((B1.Y1 - S) == 0) || ((B1.X2 - S) == 0) || ((B1.Y2 - S) == 0))
            return Box(0, 0, 0, 0);                                                         //Returns 0's because it becomes a point.
        else
            return Box(B1.X1 + S, B1.Y1 + S, B1.X2 + S, B1.Y2 + S);                         //Return the resized box.
    }
};


#endif //TYPES_H_INCLUDED

There are some limits to what you can do with a forward-declared type. In technical terms, a type that was forward-declared but not yet declared (the compiler has not reached the full declaration yet) is called an "incomplete type". The reason for that name is simple, the compiler doesn't have complete knowledge of what that type is, it only knows that it exists (or will exist in the future). So, you cannot write code that uses the class in any way, but, fortunately, you can use pointers or references to the class (but you cannot dereference them). In other words:

class MyClass; //forward-declaration

void f1( MyClass c ); // ERROR: incomplete type.

void f2( MyClass* p ); // OK!

void f3( MyClass& r ); // OK!

void f4( MyClass* p ) {
  p->someMember();   // ERROR: incomplete type.
};

Get it? The point is that the compiler can figure out what a pointer or reference looks like (in binary) without having complete knowledge of what it points to, all the compiler requires is that the pointer or reference points to an object of a valid class or type, and the purpose of the forward-declaration is to temporarily satisfy that requirement until the actual declaration appears.

So, when it comes to the code you posted, you can fix the compilation error by doing this:

struct Point
{
  //...
    Point MidPointBox (const Box& B);  // make it a reference.
  //...
};

struct Box
{
  //...
};

// then, put the implementation of MidPointBox after the declaration of the Box class:
Point Point::MidPointBox (const Box& B) {
  int MX = ((B.X1 + B.Y1)/2);  // OK, because Box has been declared now.
  int MY = ((B.X2 + B.Y2)/2);
 
  return Point(MX, MY);
};

However, satisfying the compiler is not as important as having a good software design. In your case, the function MidPointBox has no place as a member function of the Point class. At least, it should be a static member function. Better yet, it should maybe be a member function of Box. Or even better, it should be a free-function.

commented: Thanks! +6
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.