Link to home
Start Free TrialLog in
Avatar of Booth882
Booth882

asked on

msvc++/appwizard problem

I have a class I wrote, and it uses the

#ifndef __class_h
#define __class_h

class definition....

#endif

format.  the problem is when I try to include it in an appwizard program I get 46 errors that list all of the functions in my class and says that they are all multiply defined symbols that have already been defined in MyApp.obj.  it says this for MainFrame.obj, MyAppView.obj and MyAppDoc.obj.  now I would think that I am including it in the wrong place or doing something else wrong but when I include another of my user defined classes in that same place (right after #include "resource.h" in MyApp.h) it compiles just fine!  so it must be something to do with the class but I have looked over and over it and can see nothing that makes it any different from any of my other classes.  I have even made a non appwizard program and included it and it works just fine!!!  can somebody please shed some light as to what is going on?  thank you.
Avatar of Booth882
Booth882

ASKER

here is the code for the class:

#ifndef __creature_h
#define __creature_h

#include <array.h>

enum CreatureDirection
{
      Still,
      Up,
      Down,
      Left,
      Right,
      Towards,
      Away
};

class creature
{
private:
      int Size;
      int CurrentSegment;
      int LastSegment;
      array<int> XValues;
      array<int> YValues;
      array<int> ZValues;
      int XAdjust;
      int YAdjust;
      int ZAdjust;
      int XLimit;
      int YLimit;
      int ZLimit;
public:
      creature(int InitialSize, int InitialXLimit, int InitialYLimit, int InitialZLimit);
      ~creature();

      int GetSize(){return Size;};
      void GetHead(int & XCast, int & YCast);
      void GetHead(int & XCast, int & YCast, int & ZCast);
      void GetTail(int & XCast, int & YCast);
      void GetTail(int & XCast, int & YCast, int & ZCast);
      void GetSegment(int Which, int & XCast, int & YCast);
      void GetSegment(int Which, int & XCast, int & YCast, int & ZCast);
      void SetSegment(int Which, int XPosition, int YPosition);
      void SetSegment(int Which, int XPosition, int YPosition, int ZPosition);
      void AddSegment(int Number);
      void SetXAdjust(int NewXAdjust){XAdjust = NewXAdjust;};
      void SetYAdjust(int NewYAdjust){YAdjust = NewYAdjust;};
      void SetZAdjust(int NewZAdjust){ZAdjust = NewZAdjust;};
      void SetDirection(int Direction);
      void ValueAdjust(array<int> & Values, int Adjust, int Limit);
      void MoveCreature();
};

creature::creature(int InitialSize, int InitialXLimit, int InitialYLimit, int InitialZLimit)
{
      Size = InitialSize;
      XLimit = InitialXLimit;
      YLimit = InitialYLimit;
      ZLimit = InitialZLimit;
      
      XValues.MakeSize(Size);
      YValues.MakeSize(Size);
      ZValues.MakeSize(Size);
      
      CurrentSegment = 0;
      LastSegment = 1;
      SetSegment(0, XLimit / 2, YLimit / 2, ZLimit / 2);
      
      int TempX = 0;
      
      for(int b = 1; b < Size; b++)
      {
            TempX = XLimit / 2 - (Size - b);
            if(TempX > XLimit)
                  TempX -= (XLimit + 1);
            if(TempX < 0)
                  TempX += (XLimit + 1);
            SetSegment(b, TempX, YLimit / 2, ZLimit / 2);
      }

      XAdjust = 1;
      YAdjust = 0;
      ZAdjust = 0;
}

creature::~creature()
{
}

void creature::GetHead(int & XCast, int & YCast)
{
      XCast = XValues[CurrentSegment];
      YCast = YValues[CurrentSegment];
}

void creature::GetHead(int & XCast, int & YCast, int & ZCast)
{
      XCast = XValues[CurrentSegment];
      YCast = YValues[CurrentSegment];
      ZCast = ZValues[CurrentSegment];
}

void creature::GetTail(int & XCast, int & YCast)
{
      XCast = XValues[LastSegment];
      YCast = YValues[LastSegment];
}

void creature::GetTail(int & XCast, int & YCast, int & ZCast)
{
      XCast = XValues[LastSegment];
      YCast = YValues[LastSegment];
      ZCast = ZValues[LastSegment];
}

void creature::GetSegment(int Which, int & XCast, int & YCast)
{
      XCast = XValues[Which];
      YCast = YValues[Which];
}

void creature::GetSegment(int Which, int & XCast, int & YCast, int & ZCast)
{
      XCast = XValues[Which];
      YCast = YValues[Which];
      ZCast = ZValues[Which];
}

void creature::SetSegment(int Which, int XPosition, int YPosition)
{
      XValues[Which] = XPosition;
      YValues[Which] = YPosition;
}

void creature::SetSegment(int Which, int XPosition, int YPosition, int ZPosition)
{
      XValues[Which] = XPosition;
      YValues[Which] = YPosition;
      ZValues[Which] = ZPosition;
}

void creature::AddSegment(int Number)
{
      int Void = -1;
      
      for(int n = 0; n < Number; n++)
      {
            XValues.AddToArray(Void);
            YValues.AddToArray(Void);
            ZValues.AddToArray(Void);

            Size++;
      }

      if(LastSegment == 0)
            LastSegment = CurrentSegment + 1;
}

void creature::SetDirection(int Direction)
{
      switch(Direction)
      {
      case Up:
            XAdjust = 0;
            YAdjust = 1;
            ZAdjust = 0;
            break;
      case Down:
            XAdjust = 0;
            YAdjust = -1;
            ZAdjust = 0;
            break;
      case Left:
            XAdjust = -1;
            YAdjust = 0;
            ZAdjust = 0;
            break;
      case Right:
            XAdjust = 1;
            YAdjust = 0;
            ZAdjust = 0;
            break;
      case Towards:
            XAdjust = 0;
            YAdjust = 0;
            ZAdjust = -1;
            break;
      case Away:
            XAdjust = 0;
            YAdjust = 0;
            ZAdjust = 1;
            break;
      }
}

void creature::ValueAdjust(array<int> & Values, int Adjust, int Limit)
{
      Values[LastSegment] = Values[CurrentSegment] + Adjust;
      if(Values[LastSegment] > Limit)
            Values[LastSegment] = 0;
      if(Values[LastSegment] < 0)
            Values[LastSegment] = Limit;
}

void creature::MoveCreature()
{
      ValueAdjust(XValues, XAdjust, XLimit);
      ValueAdjust(YValues, YAdjust, YLimit);
      ValueAdjust(ZValues, ZAdjust, ZLimit);
      
      CurrentSegment += 1;
      if(CurrentSegment >= Size)
            CurrentSegment = 0;
      LastSegment += 1;
      if(LastSegment >= Size)
            LastSegment = 0;
}

#endif



where <array.h> is my own array class.
ASKER CERTIFIED SOLUTION
Avatar of prasanth
prasanth

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
but then why do my other user defined classes work?  they are in the same format.
I'm not sure but the #ifndef __class_h will only keep out multiple copies of header files from being included in the SAME file. But what is happening right now is that (for example) there is a create::AddSegment in MyApp.cpp, another create::AddSegment in MainFrame.cpp, yet another create::AddSegment in MyAppView, and so on. And it is the linker generating errors about finding more than one implementation for each function when it links together all the obj files.

How many other user defined classes do you have? Is each of those classes in one .h file, both definition and implementation? Can you maybe post another of your classes that works?


alright there are no more multiply defined but there is a fatal error at the end of "creature.cpp" that says "unexpected end of file while looking for precompiled header directive."  what's going on now.  oh I inserted the file into the project and included <creature.h> in creature.cpp, but I gathered I was supposed to do that from the way the other .cpps are designed.  

I attempt to use primarily my own classes just because I can adjust them whenever I need to and I gain an intimate knowledge of the objects I'm working with.  and so far yes, all of them have been declaration and implementation in the same .h file and I have had no trouble until now.  I always saw that they divided things into a .h and a .cpp but I thought it was more out of style and had nothing to do with the way it actually worked.  and other classes I have work fine in appwizard!!  it just doesnt make any sense.  I will post another class that works so you can check to see if I am doing anything different in the two, but I havent been able to see it.
#ifndef __array_h
#define __array_h

#include <stdio.h>
#include <stdarg.h>

template <class T>
class array
{
private:
      T * TheArray;
      int TheLength;
public:
      array();
      array(int InitialLength);
      array(array & CopyArray);
      ~array();

      array & operator=(array & ArrayReference);
      array & operator=(int const TheInt);
      T & operator[](int Offset);
      
      int GetTheLength(){return TheLength;};
      T * GetTheArray(){return TheArray;};
      void GrowTheArray(int AmountOfGrowth);
      void ShrinkTheArray(int AmountOfShrank);
      void MakeSize(int NewSize);
      void AddToArray(T & TReference);
      void AssignArray(int InputCount, ...);
};

template <class T>
array<T>::array()
{
      TheLength = 4;
      TheArray = new T[TheLength];
      for(int hon = 0; hon < TheLength; hon++)
            TheArray[hon] = 0;
}

template <class T>
array<T>::array(int InitialLength)
{
      TheLength = InitialLength;
      TheArray = new T[TheLength];
      for(int hon = 0; hon < TheLength; hon++)
            TheArray[hon] = 0;
}

template <class T>
array<T>::array(array & CopyArray)
{
      TheLength = CopyArray.GetTheLength();
      TheArray = new T[TheLength];
      for(int boj = 0; boj < TheLength; boj++)
            TheArray[boj] = CopyArray[boj];
}

template <class T>
array<T>::~array()
{
      delete [] TheArray;
      TheArray = 0;
}

template <class T>
array<T> & array<T>::operator=(array<T> & ArrayReference)
{
      int TheDifference = (ArrayReference.GetTheLength() - TheLength);
      if(TheDifference > 0)
            GrowTheArray(TheDifference);

      if(TheDifference < 0)
            ShrinkTheArray(0 - TheDifference);
      
      for(int Pount = 0; Pount < TheLength; Pount++)
            TheArray[Pount] = ArrayReference[Pount];
      
      return *this;
}

template <class T>
array<T> & array<T>::operator=(int const TheInt)
{
      if(TheInt == 0)
      {
            for(int j = 0; j < TheLength; j++)
                  TheArray[j] = 0;
      }

      return *this;
}

template <class T>
T & array<T>::operator[](int Offset)
{
      return TheArray[Offset];
}

template <class T>
void array<T>::GrowTheArray(int GrowthAmount)
{
      if(GrowthAmount < 1)
            return;
      
      int TempLength = TheLength + GrowthAmount;
      T * TempT = new T[TempLength];

      for(int i = 0; i < TheLength; i++)
            TempT[i] = TheArray[i];
      for(int u = TheLength; u < TempLength; u++)
            TempT[u] = 0;

      delete [] TheArray;
      TheArray = TempT;
      TheLength = TempLength;
}

template <class T>
void array<T>::ShrinkTheArray(int AmountOfShrank)
{
      int TempLength = TheLength - AmountOfShrank;
      if(TempLength < 1)
            return;
      
      T * TempT = new T[TempLength];

      for(int h = 0; h < TempLength; h++)
            TempT[h] = TheArray[h];

      delete [] TheArray;
      TheArray = TempT;
      TheLength = TempLength;
}

template<class T>
void array<T>::MakeSize(int NewSize)
{
      if(NewSize == TheLength)
            return;
      if(NewSize > TheLength)
      {
            GrowTheArray(NewSize - TheLength);
            return;
      }
      if(NewSize < TheLength)
      {
            ShrinkTheArray(TheLength - NewSize);
            return;
      }
}

template<class T>
void array<T>::AddToArray(T & TReference)
{
      GrowTheArray(1);
      TheArray[TheLength - 1] = TReference;
}

template<class T>
void array<T>::AssignArray(int InputCount, ...)
{
      if(InputCount > TheLength)
            GrowTheArray(InputCount - TheLength);
            
      va_list TheArguments;

      va_start(TheArguments, InputCount);
      for(int pp = 0; pp < InputCount; pp++)
            TheArray[pp] = va_arg(TheArguments, T);
      va_end(TheArguments);
}

typedef array<int> intarray;
typedef array<float> floatarray;

#endif

Okay, template classes are different. When you define a function for a template class, you really aren't defining a function and that is why the linker won't think there are multiple copies of a function.

So for template classes you can put everything in a .h file. but for other types of classes you need to have a separate cpp and h files - it is not just a matter of style.

The error about the precompiled header directive is because you need to include stdafx.h at the beginning of all your .cpp files.
thank you much