I'm a first-year college student that doesn't know everything about CS yet, so please bear with my newness to it, and this is my first question on here.
For an assignment, we are making faux version of Pokemon Go to practice using polymorphism in c++, and I'm running into some compiler errors. Here are the three files with just a sample of the code in them:
#ifndef EVENT_H
#define EVENT_H
#include <string>
#include "Trainer.h"
class Event{
protected:
std::string title;
public:
Event();
~Event();
virtual void action(Trainer) = 0;
};
#endif
Trainer.h:
#ifndef TRAINER_H
#define TRAINER_H
#include "Pokemon.h"
class Trainer{
private:
Pokemon* pokemon;
int num_pokemon;
public:
Trainer();
~Trainer();
//include accessors and mutators for private variables
};
#endif
Pokemon.h:
#ifndef POKEMON_H
#define POKEMON_H
#include "Event.h"
#include <string>
class Pokemon : public Event{
protected:
std::string type;
std::string name;
public:
Pokemon();
~Pokemon();
virtual bool catch_pokemon() = 0;
};
#endif
The trainer.h file is a parent class for each pokemon type (eg Rock) which just defines a few virtual functions. The error I'm getting is when I'm compiling all of this and I get something that says:
Pokemon.h : 5:30: error: expected class-name befoer '{' token:
class Pokemon : Event {
Pokemon need to be a derived class to an event, so that an event pointer can point in another Location class can point to either a pokemon, pokestop, or cave for the assignment, and I have been looking online for hours and can't figure out what to do. I would appreciate the help! Let me know if you need more info or something because again, this is my first time posting a question.
You need some forward declarations.
In Event.h, you can put class Trainer; instead of #include "Trainer.h". In Trainer.h, you can put class Pokemon; instead of #include "Pokemon.h".
You will probably need to include the appropriate headers in the corresponding source files in order to actually use the other classes. But by avoiding the includes in the header files, you get out of the circular dependency trouble.
Pokemon.h must continue to #include "Event.h", since you're inheriting Event, which requires a complete definition.
Use forward declaration, to tell classes the type they need to use will be defined later. You can use forward declaration in situations where the size is know, pointers and references are always the same size regardless of the type they point to so use them.
#ifndef EVENT_H
#define EVENT_H
#include <string>
class Trainer;
class Event
{
protected:
std::string title;
public:
Event();
virtual ~Event();
virtual void action(Trainer* const trainer) = 0;
};
#endif
then
#ifndef TRAINER_H
#define TRAINER_H
class Pokemon;
class Trainer
{
private:
Pokemon* const pokemon;
int numPokemon;
public:
Trainer();
~Trainer();
};
#endif
then
#ifndef POKEMON_H
#define POKEMON_H
#include "Event.h"
#include <string>
class Pokemon : public Event
{
protected:
std::string type;
std::string name;
public:
Pokemon();
virtual ~Pokemon();
virtual bool catchPokemon() = 0;
};
#endif
when using polymorphism (virtual functions) you must always make the base class destructor virtual too. It is also nice to make the derived classes destructor virtual as well, but it is not required.
Related
I´m building a program with several classes (data structures like stacks, lists,etc).
There is some class (Concesionario) that i need to use in another (ListaE). The class ListaE uses another class called NodoListaE, which uses two pointers, one to the value of the object (Concesionario) and another to the next position of the list (siguiente).
#ifndef NODOLISTAE_HPP
#define NODOLISTAE_HPP
#include "Concesionario.hpp"
class Concesionario;
class ListaE;
class NodoListaE
{
public:
NodoListaE(Concesionario* conc, NodoListaE* sig = NULL);
private:
Concesionario* conc;
NodoListaE* siguiente;
friend class ListaE;
};
typedef NodoListaE* pnodoListaE;
#endif // NODOLISTAE_HPP
#ifndef LISTAE_HPP
#define LISTAE_HPP
#include "NodoListaE.hpp"
#include "Automovil.hpp"
class Automovil;
class NodoListaE;
class ListaE
{
private:
NodoListaE* primero;
public:
ListaE();
void enlistarOrden(Automovil* automovil);
};
#endif // LISTAE_HPP
#ifndef CONCESIONARIO_HPP
#define CONCESIONARIO_HPP
#include <string>
#include "ListaE.hpp"
class ListaE;
class Concesionario
{
public:
Concesionario();
~Concesionario();
std::string mostrar();
void setZona(std::string letra);
void setNum();
int getNum();
private:
int nc=2;
int num_conc;
std::string zona;
int generadorNumsIntervalo(int min, int max);
ListaE automoviles;//ERROR HERE
};
#endif // CONCESIONARIO_HPP
All the cpp files are not implemented (empty constructor and destructor).
The compiler I´m currently using is MINGWx64.
I´ve tried using forward declarations and it worked for the rest of the classes but not for this one.
The program throws the following error in the **Concesionario ** hpp file: include\Concesionario.hpp|22|error: field 'automoviles' has incomplete type 'ListaE'|
Concesionario is implemented in other classes and the program runs perfectly.
Example of another class implementing Concesionario
#ifndef ARBOL_HPP
#define ARBOL_HPP
#include <iostream>
#include "NodoArbol.hpp"
#include "Concesionario.hpp"
using namespace std;
class Arbol {
public:
Arbol();
void Insertar(Concesionario* concesionario);
private:
pnodoArbol raiz;
pnodoArbol actual;
int contador;
int altura;
bool Vacio(pnodoArbol nodo);
};
#endif // ARBOL_HPP
I`ve also tried deleting this class and creating another one from 0 but the error remains.
Any solution to this problem? Thank you very much.
I'm trying to implement dependency injection in a C++ project. However, due to the structure of the dependencies, I'm getting a segmentation fault which I can't solve.
As an example I constructed the following classes and interfaces. I have a class called MyClass which has a dependency on Dependency. Dependency has a dependency on OtherDependency. To allow for proper testing, I inherit the dependencies from an interface, i.e. IDependency and IOtherDependency. OtherDependency has a function some_function().
In main.cpp I create an instance of MyClass and then try to call some_function(). Unfortunately, this gives a segmentation fault:
Segmentation fault (core dumped)
MyClass.h:
#ifndef MYCLASS_H
#define MYCLASS_H
#include "IDependency.h"
class MyClass
{
public:
MyClass(IDependency *dependency);
~MyClass();
IDependency *_dependency = nullptr;
};
#endif
MyClass.cpp:
#include "MyClass.h"
#include <iostream>
MyClass::MyClass(IDependency *dependency) : _dependency(dependency) {}
MyClass::~MyClass() {}
Dependency.h:
#ifndef DEPENDENCY_H
#define DEPENDENCY_H
#include "IDependency.h"
#include "IOtherDependency.h"
class Dependency : public IDependency
{
public:
Dependency(IOtherDependency *other_dependency);
~Dependency();
IOtherDependency *_other_dependency = nullptr;
};
#endif
Dependency.cpp:
#include "Dependency.h"
#include <iostream>
Dependency::Dependency(IOtherDependency *other_dependency) : _other_dependency(other_dependency) {}
Dependency::~Dependency() {}
IDependency.h:
#ifndef IDEPENDENCY_H
#define IDEPENDENCY_H
#include "IOtherDependency.h"
class IDependency
{
public:
IOtherDependency *_other_dependency;
};
#endif
OtherDependency.h:
#ifndef OTHERDEPENDENCY_H
#define OTHERDEPENDENCY_H
#include "IOtherDependency.h"
class OtherDependency : public IOtherDependency
{
public:
OtherDependency();
~OtherDependency();
void some_function();
};
#endif
OtherDependency.cpp:
#include "OtherDependency.h"
#include <iostream>
OtherDependency::OtherDependency() {}
OtherDependency::~OtherDependency() {}
void OtherDependency::some_function()
{
std::cout << "I am OtherDependency." << std::endl;
}
IOtherDependency.h:
#ifndef IOTHERDEPENDENCY_H
#define IOTHERDEPENDENCY_H
class IOtherDependency
{
public:
virtual void some_function() = 0;
};
#endif
main.cpp:
int main()
{
OtherDependency *other_dependency = new OtherDependency;
Dependency *dependency = new Dependency(other_dependency);
MyClass my_class(dependency);
my_class._dependency->_other_dependency->some_function();
}
What am I doing wrong / do I need to change?
You have two variables called _other_dependency: one in IDependency, the other in Dependency. The Dependency constructor initialized the latter, while the one in the IDependency class retains its default nullptr value.
When you access my_class._dependency->_other_dependency, the other_dependency will be the one in IDependency, because _dependency points to the base class.
One way to fix this is to remove the other_dependency from Dependency, and pass the value from the Dependency constructor to IDependency to properly initialize its member.
Hullo, first time asking a question! I have 3 classes, CharacterBuilder, which is an abstract class, BullyCharacterBuilder, which inherits from CharacterBuilder and redefines one of its functions, and Character, which is a generic class full of ints with accessors/mutators that I need to use.
I define a pointer to Character in CharacterBuilder.h like so:
#ifndef CHARACTERBUILDER_H
#define CHARACTERBUILDER_H
#include "Character.h"
class CharacterBuilder {
public:
Character* getCharacter();
void createNewCharacter();
virtual void buildCharacter(int level) = 0;
protected:
Character* leeroy;
};
#endif
CharacterBuilder.cpp
#include "CharacterBuilder.h"
#include "Character.h"
Character* leeroy;
Character* CharacterBuilder::getCharacter() {
return leeroy;
}
void CharacterBuilder::createNewCharacter(){
leeroy = new Character;
}
Then I inherit publicly from CharacterBuilder in my BullyCharacterBuilder class like so:
#ifndef BULLYCHARACTERBUILDER_H
#define BULLYCHARACTERBUILDER_H
#include "Character.h"
#include "CharacterBuilder.h"
class CharacterBuilder;
class BullyCharacterBuilder : public CharacterBuilder{
CharacterBuilder* myParent;
void buildCharacter(int level);
};
#endif
Finally, in the cpp file for my BullyCharacterBuilder, I attempt to call accessor/mutators from the Character pointer (which I assume I've inherited from CharacterBuilder) like so:
#include "Character.h"
#include "BullyCharacterBuilder.h"
#include "CharacterBuilder.h"
void buildCharacter(int level){
leeroy->setAbilityScores();
}
When I attempt to do this, I get Error: identifier "leeroy" is undefined
It might be a dumb question but I tried searching for this particular problem on stackoverflow and google using every combination of keywords I could think of. Would be much obliged to any help!
You forgot to qualify the function buildCharacter with your class name BullyCharacterBuilder:
void BullyCharacterBuilder::buildCharacter(int level){
leeroy->setAbilityScores();
}
you need to implement buildCharacter as a method on the CharacterBuilder class
void BullyCharacterBuilder::buildCharacter(int level)
{
leeroy->setAbilityScores();
}
if you type like this void buildCharacter(int level) meaning that the function is independent and don't belong to any class,
so you must type like this
void BullyCharacterBuilder::buildCharacter(int level) to tell compiler the function belongs to BullyCharacterBuilder
I'm starting to learn C++ (coming from Java), so bear with me.
I can't seem to get my method declaration to accept a class I've made.
'Context' has not been declared
I think I'm not understanding a fundamental concept, but I don't know what.
Expression.h
#include "Context.h"
class Expression {
public:
void interpret(Context *); // This line has the error
Expression();
virtual ~Expression();
};
Context.h
#include <stack>
#include <vector>
#include "Expression.h"
class Context {
private:
std::stack<Expression*,std::vector<Expression*> > theStack;
public:
Context();
virtual ~Context();
};
You have to forward declare Expression in Context or vice versa (or both), otherwise you have a cyclic dependency. For example,
Expression.h:
class Context; // no include, we only have Context*.
class Expression {
public:
void interpret(Context *); // This line has the error
Expression();
virtual ~Expression();
};
Context.h:
#include <stack>
#include <vector>
class Expression; // No include, we only have Expression*
class Context {
private:
std::stack<Expression*,std::vector<Expression*> > theStack;
public:
Context();
virtual ~Context();
};
You can perform the forward declarations because the full definition of the classes isn't needed, since you are only referring to pointers to the other class in each case. It is likely that you will need the includes in the implementation files (that is, #include "Context.h" in Expression.cpp and #include Expression.h in Context.cpp).
Finally, remember to put include guards in your header files.
In C++, class definitions always have to end with a semi-colon ;
so example:
class foo {};
Java and C# doesn't require that, so I can see your confusion.
Also it looks like both your header files include each other. Thus it's kind of like a snake eating it's tail: Where does it start? Thus in your Expression.h you can replace the 'include' with a forward declaration instead:
class Context;
class Expression {
public:
void interpret(Context *); // This line has the error
Expression();
virtual ~Expression();
}
And last but not least, you should put a compiler guard to prevent the header from getting included more than once into a .cpp file. You can put a #pragma once in the top of the header file. That is useful if you are using visual studio and the microsoft compiler. I don't know if GCC supports it or not. Or you can wrap your header file like this:
#ifndef EXPRESSION_H_
#define EXPRESSION_H_
class Context;
class Expression {
public:
void interpret(Context *); // This line has the error
Expression();
virtual ~Expression();
}
#endif
you might need to forward declare the classes Context and Expression in the header files before the #include
e.g.
#include <stack>
#include <vector>
// forward declaration
class Context;
class Expression;
#include "Expression.h"
class Context {
private:
std::stack<Expression*,std::vector<Expression*> > theStack;
public:
Context();
virtual ~Context();
}
Hi am having problems compiling some code, I have a situation where A depends and B depends on A. I have put forward declarations but I keep getting the problems.
In file included from src/MemoWriteContext.h:7:0,
from src/MemoWriteContext.cpp:1:
src/MemoContext.h:29:20: error: field ‘memoWriteContext’ has incomplete type
MemoContext.h
#ifndef MEMOCONTEXT_H_
#define MEMOCONTEXT_H_
#include "sqlite/SqliteDb.h"
#include "Context.h"
#include "MemoWriteContext.h"
#include <string>
#include <memory>
#include <map>
namespace bbs
{
class MemoWriteContext;
class MemoContext : public Context
{
public:
//'structors
MemoContext(const std::map<std::string, std::shared_ptr<Context> > &_contexts,
sqlitecpp::SqliteDb &_sqliteDb);
~MemoContext();
protected:
//when called write the data back to the user
void performAction(const std::string &data, std::shared_ptr<UserAgent> agent);
private:
MemoWriteContext memoWriteContext;
}; //class memocontext
}
#endif // MEMOCONTEXT_H_
MemoWriteContext.h
#ifndef MEMOWRITECONTEXT_H_
#define MEMOWRITECONTEXT_H_
#include "Context.h"
#include "sqlite/SqliteDb.h"
#include "sqlite/PreparedStmt.h"
#include "MemoContext.h"
#include <string>
#include <memory>
#include <map>
namespace bbs
{
class MemoContext; //forward decl
class MemoWriteContext : public Context
{
public:
//'structors
MemoWriteContext(const std::map<std::string, std::shared_ptr<Context> > &_contexts,
MemoContext &_memoContext, sqlitecpp::SqliteDb &_sqliteDb);
~MemoWriteContext();
protected:
//when called write the data back to the user
virtual void performAction(const std::string &data, std::shared_ptr<UserAgent> agent);
virtual void onReceiveUserAgent(std::shared_ptr<UserAgent> agent);
private:
MemoContext &memoContext; //parent;
sqlitecpp::SqliteDb &sqliteDb;
sqlitecpp::PreparedStmt writeMemoStmt;
sqlitecpp::PreparedStmt findAgentIdStmt;
};
enum class MemoWriteState : char
{
USERNAME=0,
MESSAGE,
CONFIRM
};
class MemoWriteAgentData : public ContextAgentData
{
public:
MemoWriteState state;
int userId;
std::string message;
}; //class Memo Write Agent data
}
#endif // MEMOWRITECONTEXT_H_
Full source here.
I think your only problem is that MemoWriteContext.h has #include "MemoContext.h". The context only requires a reference which can use the forward declaration. But if you happen to include MemoWriteContext.h first it will then bring in MemoContext.h before it actually declares class MemoWriteContext. That will then use the forward declaration of class MemoWriteContext and fail. You can even see the ordering in your error message.
Just remove that #include or at least reverse the order of the includes in MemoWriteContext.cpp (since each .h including the other effectively reverses them back).
This:
class MemoWriteContext;
Is a forward declaration. It's an "incomplete type", and therefore cannot be instantiated.
The reason is that a C++ compiler must know the size of any type that has to be instantiated. Incomplete types have no size.
By the way, you can do this:
MemoWriteContext * ptr;
Because you actually declare a pointer, and pointers have a known size.
If you want to avoid dynamic allocations, then you'll have to fully declare the type by including MemoWriteContext.h and removing the forward declaration.