Animal
|
Mammal
/ \
TwoLegged - FourLegged
/ \
Human Lion
I have this class hierarchy, each class defined in it's own header. Now when I include both
Human.h and Lion.h in the same place, I get a Mammal redefinition error.
error C2011: 'Mammal' : 'class' type redefinition
This because Mammal.h is included in both TwoLegged and OneLegged classes.
I'm not sure however, how I could resolve this cyclic dependency in headers, as I cannot change the class hierarchy.
Anybody care to assist?
EDIT:
Mammal header
#ifndef MAMMAL_H
#define MAMNAL_H
#include "stdafx.h"
#include "Animal.h"
class Mammal : public Animal
{
public:
Mammal::Mammal();
virtual Mammal::~Mammal();
std::string mammal_name();
int mammal_age();
int mammal_expectedlifedays();
bool mammal_hunter();
int mammal_power();
int mammal_birthrate();
bool mammal_alive();
protected:
Mammal::Mammal(const std::string& mname, int mexpectedlifedays, int mage, bool mhunter, int mpower, int mbirthrate, bool malive) : Animal(mname, mexpectedlifedays, mage,mhunter, mpower, mbirthrate, malive)
{}
private:
};
#endif
The errors given by the compiler:
error C2011: 'Mammal' : 'class' type redefinition
see declaration of 'Mammal'
error C2504: 'Mammal' : base class undefined
error C2614: 'TwoLegged' : illegal member initialization: 'Mammal' is not a base or member
Note: It's not homework, else I would have tagged it as such.
#pragma once
Add that at the very top of all your header files.
However, keep in mind that even though it is very well supported by compilers, it's not a standard.
You need to use include guards. The typical form is:
#ifndef NAME_OF_HEADER_H
#define NAME_OF_HEADER_H
// Rest of header code here.
#endif
Since #include in C++ just does a copy-paste of the text in the current file if the same header gets included twice that text will result in duplicate class definitions. What the include guard does is prevent the multiple inclusion of the same header.
EDIT: The problem is that you check for definition of MAMMAL_H and then define MAMNAL_H (note the N in the defined version). I always copy-paste to generate my include guards for precisely this reason.
I guess you forgot include guards. Use #ifndef /#ifdef/ #endif as John suggested.
#ifndef MAMMAL_H
#define MAMMAL_H
... definition of mammal
#endif
Related
Greetings oh mighty coders,
I am a beginner and in a bit of trouble here.
There is my baseclass (sensor.h):
class sensor
{
private:
int sensor_id;
string sensor_name;
string sensor_type;
float reading;
public:
sensor();
sensor(int, char*, char*);
~sensor();
/* Few extra methods here */
};
... and I want to create 4 other classes that inherit from my baseclass sensor
(temperaturesensor, humiditysensor... and so on).
#include "sensor.h"
class temperaturesensor:public sensor
{
public:
Temperatursensor(int, char*,char*);
~Temperatursensor();
/* Few extra methods here */
};
Thing is: Every single one of these classes has to be in its own .cpp/.h file and then be included and used in my main.cpp.
using namespace std;
#include <xyz.h>
/* Other libaries here */
....
#include "temperaturesensor.h"
#include "humiditysensor.h"
int main()
{
sensor* station[2];
station [0] = new temperaturesensor(x,y,z);
station [1] = new humiditysensor(x,y,z);
}
If I include one of them it's no biggie. However: If I use multiple ones I get an redefinition error.
error C2011: 'sensor': 'class' typeredefinition
c:\users\name\desktop\project\sensor.h 14
error c2011: 'temperaturesensor' : 'class' typeredefinition
What can I do to workaround this? Note that I am not allowed to use #pragma once
Sorry for my stupidity and thanks in advance!
You must use:
#ifndef FILE_H
#define FILE_H
.. normal code here
#endif
or
#pragma once
but too, I think, that sensor schould be abstract class and you schould use virtual destructor.
One more think is that array is numerate from 0.
you forgot to use the include guards in your header class,
this is redefining your base class everytime you use it.
so, just do a
#pragma once
or a normal include guard
#ifndef YOURFILENAME_H
#define YOURFILENAME_H
.. normal code here
#endif
Then you will not have the multiple definition error.
The definition of the class sensor is coming from both "temperaturesensor.h"
and "humiditysensor.h". Use guards https://en.wikipedia.org/wiki/Include_guard or #pragma once: https://en.wikipedia.org/wiki/Pragma_once
For a C++-project, I need to make a game with Doodlebugs and Ants, which are both Organisms. So, I made a class called Organism with the following definition (although I'll probably add way more member functions and member variables, of course).
Organism.h:
#ifndef ORGANISM_H
#define ORGANISM_H
#include "World.h"
class Organism
{
public:
Organism();
~Organism();
virtual void Move() = 0;
friend class World;
int survivalTime;
};
#endif
Organisms live in 'the World', which is a class with (among others) a member variable Organism*** field, a two-dimensional dynamic array containing pointers to Organism objects.
World.h:
#ifndef WORLD_H
#define WORLD_H
#include "Organism.h"
#include "Ant.h"
#include "Doodlebug.h"
class World
{
public:
World();
~World();
void gameplay();
Organism*** field;
};
#endif
You probably already guessed it: Ant and Doodlebug are derived from Organism.
Ant.h:
#ifndef ANT_H
#define ANT_H
#include "Organism.h"
class Ant : public Organism
{
public:
Ant();
~Ant();
void Move();
};
#endif
Doodlebug.h:
#ifndef DOODLEBUG_H
#define DOODLEBUG_H
#include "Organism.h"
class Doodlebug : public Organism
{
public:
Doodlebug();
~Doodlebug();
void Move();
};
#endif
As you can see, Ant.h and Doodlebug.h are almost identical, except for the words Doodlebug and Ant. However, I have two errors.
In World.h, line 16: "'Organism' does not name a type."
In Doodlebug.h, line 7: "expected class-name before '{' token"
Why is this? The first error can be solved by putting class Organism; right before the definition of class World, but I don't understand why that changes anything, since the complete definition of Organism is in Organism.h, which I include.
The second error is the one I'm VERY confused by (and kind of the main reason I'm asking this question), since Ant.h is identical to Doodlebug.h except for the words Ant and Doodlebug, but in Doodlebug.h I get an error but not in Ant.h???
Any help is greatly appreciated.
You have circular dependency between World.h and Organism.h.
World.h has
#include "Organism.h"
and Organism.h has
#include "World.h"
You can remove the above line from Organism.h and replace it with a forward declaration.
class World;
Use forward declaration in header files if you don't need the definition of a as a matter of principle. That will not only avoid problems like the one you encountered but it will also reduce compile time dependecies.
Additional references:
Forward declaration vs include
When can I use a forward declaration?
You did not post your compile command (and most importantly what is the file you try to compile?), but below is what I think your problem is.
The main problem is that your Organism.h includes World.h, which in turn tries to include Organism.h once again, but does not actually include it due to include guards. Therefore, in World.h the compiler still does not know what Organism is and thus generates the first error. You can use forward declaration to solve this: just write
class Organism;
in World.h before class World...; you can also remove #include "Organism.h" from World.h.
I suppose that your second problem can be related to this also.
Note that you can use -E parameter to g++ to generate the file as compiler sees it after preprocessing. Very useful to catch these include-related problems.
The first issue derives from your include "mess". When Organism.h is processed (maybe because a corresponding Organism.cc is compiled) the include statement is replaced by the actual contents, i.e. it is replaced by the contents of World.h. That effectively yields a translation unit where the declaration of World stands before the declaration of Organism, hence leading to the error.
You could also probably remove #include "Organism.h" from your World.h as you have included that in both your Ant and Doodlebug classes, and both of those are included in your World class.
I have problem. I want to have one global pointer containing adress of my class. And this pointer should be visible for all other parts of program. This is my source code of objects:
//FILEname:LP_poGlobalObject.cpp
#include "LP_poGlobalObject.h" //this is header file to be included by all other files
#include "LP_PSI_Object.h" //include oPsiTestStrategy class
oPsiTestStrategy* poGlobalObject = NULL;
//create new pointer supposed to be global
this is header file for this global variable pointer
//FILEname:LP_poGlobalObject.h
#if !defined LP_PSI_OBJECT_GLOBAL_H
#define LP_PSI_OBJECT_GLOBAL_H
extern oPsiTestStrategy* poGlobalObject; //error C2143: syntax error : missing '{' before '*'
#endif
At the marked line I get a compiler error:
error C2143: syntax error : missing '{' before '*'
and this is class oPsiTestStrategy used above
//FILEname:LP_PSI_Object.h
#if !defined LP_PSI_OBJECT_H
#define LP_PSI_OBJECT_H
class oPsiTestStrategy
{
public:
oPsiTestStrategy();
virtual ~oPsiTestStrategy();
virtual Word zPsiGetSourceId_Testing_O(EvtId xEvtPktId);
virtual Dword zPsiGetData_Testing_O(EvtId, void*);
virtual Dword zPsiGetDataLen_Testing_O( EvtId );
virtual void vPsiExitEvent_Testing_O( EvtId );
virtual void vPsiCancelEvent_Testing_O( EvtId );
virtual void vPsiSetUserStatus_Testing_O( EvtId , Word );
};
#endif
// methods are virtual because I want to test this and replace it with mock objects - GTest, UnitTesting.
//Is this causing my problem?
Desired result of this should be something like this:
#include "LP_poGlobalObject.h"
int main()
{
poGlobalObject->vPsiCancelEvent_Testing_O((EvtId)5);
}
Thanks people, have a nice day.. :-)
oPsiTestStrategy type is not know at the point where you use it in LP_poGlobalObject.h. You have to reorder the includes:
#include "LP_PSI_Object.h" //include oPsiTestStrategy class
#include "LP_poGlobalObject.h" //this is header file to be included by all other files
You could also include LP_PSI_Object.h in LP_poGlobalObject.h or make a forward declaration for oPsiTestStrategy before defining an external object of that type.
In your header file add - before definition of global variable...
class oPsiTestStrategy;
So the compiler knows what a oPsiTestStrategy is...
oPsiTestStrategy has to be defined or forward declared when
extern oPsiTestStrategy* poGlobalObject;
is declared, otherwise it is not known to the compiler.
Add include directive
#include "LP_poGlobalObject.h"
#include "LP_PSI_Object.h"
or forward declaration for oPsiTestStrategy type:
class oPsiTestStrategy;
I get the error "C2143: syntax error: missing ';' before '*' in Track.h
I believe this is due to a "missing" class definition.
These are the 3 header files:
Topics.h, the package-level header file, which #includes everything else:
#ifndef Topics_H
#define Topics_H
#include <oxf\oxf.h>
#include "Request.h"
#include "TDPoint.h"
#include "Track.h"
#include "TrackReport.h"
#endif
Then there's TDPoint (as in "3DPoint"), which simply defines a class with 3 long attributes:
#ifndef TDPoint_H
#define TDPoint_H
#include <oxf\oxf.h> // Just IBM Rational Rhapsody's Framework
#include "Topics.h"
class TDPoint {
//// Constructors and destructors ////
public :
TDPoint();
~TDPoint();
//// Additional operations ////
long getX() const;
void setX(long p_x);
long getY() const;
void setY(long p_y);
long getZ() const;
void setZ(long p_z);
//// Attributes ////
protected :
long x;
long y;
long z;};
#endif
But the problem lies here, in the marked line:
#ifndef Track_H
#define Track_H
#include <oxf\oxf.h> // Just IBM Rational Rhapsody's Framework
#include "Topics.h"
#include "TDPoint.h"
class Track {
public :
//// Operations ////
std::string getId() const;
void setId(std::string p_id);
TDPoint* getPosition() const; // <--- This line, the first line to use TDPoint, throws the error
//// Attributes ////
protected :
std::string id;
TDPoint position;
public :
Track();
~Track();
};
#endif
My guess was that the compiler (MS VS2008/ MSVC9) simply didn't know the class "TDPoint." But even defining the class in the same header file as "Track", or using a forward declaration like "class TDPoint" (which then throws the error: undefined class) didn't help.
The code was auto-generated from Rhapsody, if that makes any difference.
But maybe the error is something else entirely?
Topics.h includes TDPoint.h and Track.h
TDPoint.h includes Topics.h
and Track.h includes both Topics.h and TDPoint.h
This feels like a circular include... You should either forward declare your classes to solve it or modify Topics.h to not to have circularity.
You have circular inclusion: The file Track.h includes Topics.h which includes TDPoints.h which includes Topics.h which includes Track.h where the TDPoint class is not declared.
In fact, the TDPoint.h doesn't need any header files at all, it's completely independant (as per the code shown in your question).
The Track.h file only needs to include TDPoint.h, not Topics.h. (And possibly <string>.)
General hint: Include as few headers as possible in a header file.
The other answers are correct, but I would like to add few things for completeness.
1. Cause: your project have circular including, specifically, when you compile "TDPoint.cpp", the compiler will do the following
#include "TDPoint.h" //start compiling TDPoint.h
#include "Topics.h" //start compiling Topics.h
#include "TDPoint.h" //compilation of TDPoint.h skipped because it's guarded
#include "Track.h" //start compiling Track.h
#include "Topics.h" //compilation of Topics.h skipped because it's guarded
//resume compiling Track.h
...
TDPoint* getPosition() const; //=> error TDPoint is not defined
=>C2143: syntax error: missing ';' before '*'
2. Counter measure: replace including in header by forward declaration to remove circle of including, and use including in .cpp files. Specifically, forward declaration means:
(in Topics.h)
#ifndef Topics_H
#define Topics_H
#include <oxf\oxf.h>
#include "Request.h"
class TDPoint; //Forward declaration to replace #include "TDPoint.h"
class Track; //Forward declaration to replace #include "Track.h"
#include "TrackReport.h"
#endif
I'm new to C++ abstract classes and I'm trying to learn how to work with it. So I started by defining an abstract class with only pure functions, let's call this class SceneObj, so far so good. Afterwards, I start by defining a new abstract class that I'm calling IScreen; this new Class is, also, another abstract class, but it add new requirements.
Unfortunately when trying to compile this simple code I ran into the following error: error C2011: 'IScreen' : 'class' type redefinition.
I'm using Visual Studio 2012 and the code that I'm trying to compile is the following:
#include <stdlib.h>
using namespace std;
class SceneObj
{
protected:
float center;
public:
virtual void SetCenter(float,float,float) = 0;
virtual void SetCenter(float) = 0;
virtual float GetCenter() = 0;
virtual ~SceneObj();
};
class IScreen : public SceneObj
{
public:
virtual void SetCenter(float,float,float) = 0;
virtual void SetCenter(float) = 0;
virtual float GetCenter() = 0;
virtual float GetStartCorner() = 0;
virtual void SetSize(float,float) = 0;
virtual void SetSize(long) = 0;
virtual long GetSize() = 0;
virtual ~IScreen();
};
Could someone point me what/where is the flaw in this code?
edit: Changed code to a minimal one
edit2: This is in a header file and apparently if i change it to a .cpp it compiles without problems. But I needed/wanted to declare my class in headers and then define then in .cpp.
C++programs also use the preprocessor to define header guards. Header guards
rely on preprocessor variables. Preprocessor variables have one of two
possible states: defined or not defined. The #define directive takes a name and defines
that name as a preprocessor variable. There are two other directives that test whether
a given preprocessor variable has or has not been defined: #ifdef is true if the variable
has been defined, and #ifndef is true if the variable has not been defined. If the test is
true, then everything following the #ifdef or #ifndefis processed up to the
matching #endif.
We can use these facilities to guard against multiple inclusion as follows:
#ifndef SALES_DATA_H
#define SALES_DATA_H
#include <string>
struct Sales_data {
std::string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
};
#endif //SALES_DATA_H
For instance, in the header file you will find something LIKE the follwing:
#ifndef __*__SceneObj
#define __*__SceneObj__
//Place the abstract class here
#endif
So you have to put the abstract class in between the #define and the #endif. (This is the definition the compiler will consider). you simply don't have these etiquettes on the cpp file. That is why it works there.
Additionally try to have one class per header file, so do not declare the child class on the same header file.
It means that somewhere you already have defined type IScreen. Usually the compiler gives a reference to the duplicated definition.
So investigate the error message.
As for you code snippet then it is irrelevant.
MS VS usually gives several messages if it found an error.
Another reason can be that you included the cpp module with member function definitions in the module with main.
For example
Header file: header.h
#include <stdlib.h>
using namespace std;
class SceneObj
{
//...
};
class IScreen : public SceneObj
{
//...
};
cpp module with member function definitions: module,cpp
#include "header.h"
//...
module with main
#include "header.h"
#include "module.cpp"
//...
Also include directive
#pragma once
in your header file.