I know there are plenty of questions like these, but I couldn't find a solution that worked for me. Anyways, I have 4 files, two header files and two cpp files, one implementation and one main.
Header File 1
#ifndef SORTEDINTERFACE_H
#define SORTEDINTERFACE_H
using namespace std;
template<class ListItemType>
class sortedInterface
{
public:
virtual int sortedGetLength() const = 0;
virtual bool sortedIsEmpty() const = 0;
virtual bool sortedInsert(const ListItemType& newItem) = 0;
virtual bool sortedRemove(const ListItemType& anItem) = 0;
virtual bool sortedRetrieve(const ListItemType& anItem) = 0;
virtual int getItemCount () = 0;
private:
virtual int locatePosition(const ListItemType& anItem) = 0;
};
#endif // SORTEDINTERFACE_H_INCLUDED
Header File 2
#ifndef SORTED_H
#define SORTED_H
#include "sortedInterface.h"
using namespace std;
template<class ListItemType>
class sorted : public sortedInterface<ListItemType>
{
public:
sorted();
int sortedGetLength() const;
bool sortedIsEmpty() const;
bool sortedInsert(const ListItemType& newItem);
bool sortedRemove(const ListItemType& anItem);
bool sortedRetrieve(const ListItemType& anItem);
int getItemCount();
private:
static const int DEFAULT_LIST_SIZE = 10;
ListItemType items[DEFAULT_LIST_SIZE];
int itemCount;
int maxItems;
int locatePosition(const ListItemType& anItem);
};
#include "sorted.cpp"
#endif // SORTED_H
CPP File
#include "sorted.h"
#include <cstddef>
using namespace std;
template<class ListItemType>
sorted<ListItemType>::sorted() : itemCount(0), maxItems(DEFAULT_LIST_SIZE)
{
} // end default constructor
Main CPP File
#include <iostream>
#include "sorted.h"
#include <cstddef>
using namespace std;
int main()
{
sorted<string> test;
return 0;
}
When I compile I get the errors/warnings
1. redefinition of 'sorted::sorted()
2. sorted::sorted()' previously declared here
When I comment out the #include "sorted.cpp" at the end of header file #2, it works, but then in my main file, it doesn't regonize my sorted test object.
Any help would be great, thanks in advance.
are you compiling sorted.cpp also . i think you should not .
If you're adding the sorted.cpp file at the end, then you must realize that sorted.cpp is not a separate module -- it is just the implementation of your template class implementation. Therefore you should remove the first three lines from that .cpp file.
#include "sorted.h"
#include <cstddef>
using namespace std;
Those lines above should not be in the template implementation file.
Also, I would rename sorted.cpp to sorted.ipp or some other extension to something indicating it is just a template implementation file and not a separate source module to be compiled.
Related
Here is the code for the question:
PlainInterface.h
/** PlainInterface.h */
#ifndef _PLAIN_INTERFACE
#define _PLAIN_INTERFACE
#include <vector>
template <class ItemType>
class PlainInterface{
public:
virtual int getSize () const = 0;
};
#endif
Plain.h
/** Plain.h */
#ifndef _PLAIN
#define _PLAIN
#include "PlainInterface.h";
template <class ItemType>
class Plain: public PlainInterface < ItemType > {
private:
std::vector<ItemType> a;
public:
Plain();
~Plain();
int getSize() const;
};
#include "Plain.cpp"
#endif
Plain.cpp
/* Plain.cpp */
#include <iostream>
#include "Plain.h"
//Constructors
template <class ItemType>
Plain<ItemType>::Plain() {
std::cout << "Created\n";
}
template <class ItemType>
Plain<ItemType>::~Plain() {
std::cout << "Destroyed\n";
}
template <class ItemType>
int Plain<ItemType>::getSize() const { return 0; }
So according to this question it said that you can either have all of the implementation in the header file, or put #include "Plain.cpp" at the end of the "Plain.h" file, or put the explicit instantiations at the end of the "Plain.cpp" file. I would like to keep the files seperate and not limit what is allowed into the templates. I tried the second option and it didn't work.
The errors that I am getting are that the constructor/deconstructor/getSize definitions in Plain.cpp are already defined. What am I doing wrong here?
You should remove #include "Plain.h" in your .cpp file, as you are creating a circular include otherwise.
Example:
//a.h
...
#include "b.cpp"
//b.cpp
#include "a.h"
a will include b, b will include a, and so on. This is probably why the second option you mentioned didn't work.
Here another answer that applies to your problem (I think): https://stackoverflow.com/a/3127374/2065501
This is strange. How can it possibly be that I get an error when I'm including an .h file (GeneralSearch.h) but everything seems to work just fine when, instead, I include the .cpp file (GeneralSearch.cpp)?
.h file
#ifndef GENERALSEARCH_H_
#define GENERALSEARCH_H_
#include "Problem.h"
#include "Node.h"
template <class T>
class GeneralSearch
{
public:
const Node* treeSearch(const Problem &problem) const;
const Node* graphSearch(const Problem &problem, T &fringe = T()) const;
private:
void expand(const Node &node, const Problem &problem, list<const Node*> &out) const;
};
#endif
.cpp file
#include "GeneralSearch.h"
template <class T>
void GeneralSearch<T>::expand(const Node &node, const Problem &problem, list<const Node*> &out) const
{
...
}
template <typename T>
const Node* GeneralSearch<T>::treeSearch(const Problem &problem) const
{
...
}
template <typename T>
const Node* GeneralSearch<T>::graphSearch(const Problem &problem, T &fringe = T()) const
{
...
}
the program file - WORKING
#include "GeneralSearch.cpp"
#include "DummyProblem.h"
#include "DepthFirstSearch.h"
#include <queue>
int main (int argc, char* argv[]){}
the program file - NOT WORKING
#include "GeneralSearch.h"
#include "DummyProblem.h"
#include "DepthFirstSearch.h"
#include <queue>
int main (int argc, char* argv[]){}
The linker tries to find the definitions of unresolved names while linking. In the second case, the linker is not able to find the definitions of the member functions of the class GeneralSearch and hence you get the error.
There is one header a file Rectangle.hxx
#ifndef Rectangle_included
#define Rectangle_included
#include <iostream>
#include <math.h>
#include "GetL.hxx"
using namespace std;
class Rectangle: public GetL
{
int width;
int value;
public:
Rectangle();
Rectangle(int v, int w);
Rectangle(const Rectangle& b);
int getWidth();
int getValue();
Rectangle & plus(int newval);
};
#endif //Rectangle_included
The file GetL.hxx is defined like this:
#ifndef GetL_included
#define GetL_included
#include <iostream>
using namespace std;
class GetL
{
public:
virtual int getWidth();
};
#endif //GetL_include
The file Rectangle.cxx contains various definitions:
#include <iostream>
#include <math.h>
#include "Rectangle.hxx"
using namespace std;
Rectangle::Rectangle()
{
value=0;
width=0;
}
Rectangle::Rectangle(int v, int w)
{
value=v;
width=w;
}
Rectangle::Rectangle(const Rectangle& b)
{
value= b.value;
width= b.width;
}
int Rectangle::getWidth()
{
return width;
}
int Rectangle::getValue()
{
return value;
}
Rectangle& Rectangle::plus(int newval)
{
value+=newval;
if(value>=pow(2,width))
cout<<"Overflow";
return *this;
}
But i am getting the error on compiling Rectangle.cxx.
/tmp/cclETn3R.o:Rectangle.cxx:(.text$_ZN4GetLC2Ev[GetL::GetL()]+0*8): undefined reference to 'vtable for Getl'
How can i remove it? How can i define file GetL.cxx or i don't need to?
You need to compile the different files without linking first. On UNIX compilers this is typically done using the -c option. When building the executable you then specify all the produced .o objects. Alternatively you can specify all source files at once but this is really only viable for very small projects.
You must implement GetL::getWidth(). Given your other files, you will probably implement it in GetL.cxx.
I've these 2 files, but the interface (and the compiler) give me this error, can you help me find what is wrong?Is really strange... should I define all body of my methods in the .cpp file?
//GameMatch.h
#pragma once
#include "Player.h"
namespace Core
{
class GameMatch
{
private:
const static unsigned int MAX_PLAYERS=20;
unsigned int m_HumanControlled;
Score* m_LastDeclaredScore;
Score* m_LastScore;
unsigned int m_MaxPlayers;
Player* m_Players[MAX_PLAYERS];
unsigned int m_PlayerTurn;
inline void NextTurn() { m_PlayerTurn=(m_PlayerTurn+1U)%m_MaxPlayers; }
public:
GameMatch(void);
~GameMatch(void);
void RemovePlayer(Player* _player);
inline Player* getPlayingPlayer() { return m_Players[m_PlayerTurn]; }
};
}
and
//Player.h
#pragma once
#include "IController.h"
#include "GameMatch.h"
#include <string>
#include <Windows.h>
using namespace Core::Controller;
using namespace std;
namespace Core
{
class Player
{
private:
IController* m_Controller;
unsigned int m_Lives;
GameMatch* m_GameMatch;
string m_Name;
bool m_TurnDone;
public:
inline void Die()
{
m_Lives-=1U;
if (m_Lives<1) m_GameMatch->RemovePlayer(this);//m_GameMatch is the first error
}
inline const string& getName() { return m_Name; }
inline bool IsPlayerTurn() { return (m_GameMatch->getPlayingPlayer()==this); }//m_GameMatch is the second error
virtual void Play()=0;
inline Player(GameMatch* _gameMatch,const char* name,unsigned int lives=3)
{
m_GameMatch=_gameMatch;
m_Name=name;
m_Lives=lives;
}
inline void WaitTurn() { while(!IsPlayerTurn()) Sleep(1); }
virtual ~Player()
{
delete m_Controller;
}
};
}
But as you can see, m_GameMatch is a pointer, so I don't understand why this error, maybe for "recursive inclusion" of header files...
UPDATE 1:
//GameMatch.h
#pragma once
#include "Score.h"
#include "Player.h"
namespace Core
{
class GameMatch
{
private:
const static unsigned int MAX_PLAYERS=20;
unsigned int m_HumanControlled;
Score* m_LastDeclaredScore;
Score* m_LastScore;
unsigned int m_MaxPlayers;
Player* m_Players[MAX_PLAYERS];
unsigned int m_PlayerTurn;
inline void NextTurn();
public:
GameMatch(void);
~GameMatch(void);
void RemovePlayer(Player* _player);
inline Player* getPlayingPlayer();
};
}
and
//Player.h
#pragma once
#include "IController.h"
#include "GameMatch.h"
#include <string>
#include <Windows.h>
using namespace Core::Controller;
using namespace std;
namespace Core
{
class Player
{
private:
IController* m_Controller;
unsigned int m_Lives;
GameMatch* m_GameMatch;
string m_Name;
bool m_TurnDone;
public:
inline void Die();
inline const string& getName();
inline bool IsPlayerTurn();
virtual void Play()=0;
inline Player(GameMatch* _gameMatch,const char* name,unsigned int lives=3);
inline void WaitTurn();
virtual ~Player();
};
}
These are the 2 headers now, however it's still not working, if I don't include Player.h and forward declare a class in this way inside GameMatch.h:
class Player;
It works, however what if I want use some Player methods?I should re-forward declare everything... isn't this what header files are done for? I can include an header file in a lot of places... why can't I do it in this case?
SOLUTION:
The answer is from Alf P. Steinbach on chat:
yes, and the answer you got seems to be correct. the cyclic header dependency is a problem. there might be other problems also, but the cyclic dependency is a big one.
you don't need a full definition of a class in order to use T*.
so the usual breaking of the cycle is to just forward-declare a class, like
class Player;
that tells the compiler that Player is a class, so you can use Player* and Player&, and even declare member functions that return Player (although you can't define such a function until Player class is fully defined)
well as a concrete example, all that's needed for the Core::GameMatch class definition is a forward declaration of class Player.
then in implementation file you can include "player.h".
if it's needed for GameMatch implementation.
if you draw the files as little boxes and draw arrows to show includes, you'll see that that gets rid of the cyclic dependency
This said, he explain that the answer I got is the correct one so I'll mark OJ's
You should definitely avoid the cyclic header include.
Break the content of your functions out into .cpp files instead of putting everything in header files. Also, rather than #include things every time, just forward declare instead.
If you remove the cyclic include, your code will most likely work.
This might be an easy question, but I cannot figure out why the compiler it's giving me this error. I have two classes. Agent and Environment. WHen I try to add an object of type Agent in my Environment class I get Agent does not name to a type error. I am including Agent.h in my Environment.h class
#ifndef AGENT_H_INCLUDED
#define AGENT_H_INCLUDED
#include <vector>
#include <iostream>
#include "Environment.h"
using namespace std;
class Agent{
public:
Agent(bool s);
vector<int> getPercept();
void setPercept(vector<int> p);
void goForward();
void turnRight();
void turnLeft();
void clean();
void paint();
void refuel();
bool needsRefuel();
void turnOn();
void turnOff();
bool isActive();
void move();
int getCurX();
int getCurY();
char getCurDir();
void setCurrentPosition(int x, int y, char d);
private:
vector<int> percept;
int actions;
int performance;
char direction;
bool isOn;
int curX;
int curY;
char curDir;
};
#endif // AGENT_H_INCLUDED
/*************************/
#ifndef ENVIRONMENT_H_INCLUDED
#define ENVIRONMENT_H_INCLUDED
#include <vector>
#include <iostream>
#include "Agent.h"
using namespace std;
class Environment{
public:
Environment(vector<vector<char> > roomData);
Environment(vector<vector<char> > roomData, vector<int> status);
void setRoomData(vector<vector<char> > roomData);
bool isSimulationComplete();
void isAgentHome();
vector<int> sendLocationStatus();
void printEnvironment();
void setAgentHome(int x, int y);
vector<int> getAgentPercept();
void setAgentPercept(vector<int> status);
void setAgentPosition(int x, int y, char p);
vector<int> sendAgentPercept();
void calculateAgentPercept();
private:
vector<vector<char> > room;
vector<int> agentPercept;
bool simulationComplete;
int agentHomeX;
int agentHomeY;
int agentX;
int agentY;
char agentDir;
Agent agent; ////ERROR IS HERE
};
#endif // ENVIRONMENT_H_INCLUDED
Your agent.h includes environment.h. The agent.h file is parsed in order from top to bottom, so when environment.h is parsed, the compiler doesn't know what an Agent is. There appears to be no reason to incude environment.h in agent.h.
Apart from what the comments already said, you can't have two header files include each other. There is no reason for Agent.h to include Environment.h, so if a .cpp file includes Agent.h first, it'll fail (since it will first go through Environment.h, which requires Agent).
IF you have a situation where two header files depend on each other's definitions, use forward declarations where you can, or split your header files up into more header files.