I have a generic class for many states for an automaton. It's declared as follows:
#ifndef STATE_H_
#define STATE_H_
#include "Automat.h"
class State {
public:
virtual void readChar(char c, Automat* automat) = 0;
virtual ~State(){};
};
#endif /* STATE_H_ */
I get this error in eclipse:
Multiple markers at this line
no known conversion for argument 2 from ‘Automat* const’ to ‘int*’
virtual void State::readChar(char, int*)
‘Automat’ has not been declared
My automat is as follows:
#ifndef Automat_H_
#define Automat_H_
#include "../../Scanner/src/IScanner.h"
#include "./States/State.h"
class Automat {
public:
int count;
State* current;
IScanner* scanner;
Automat(IScanner *s);
void readChar(char c);
void setState(State *s);
void error();
~Automat();
};
#endif /* Automat_H_ */
And finally the implementation of Automat, i will leave out some methods.
#include "Automat.h"
#include "./States/StartState.h"
Automat::Automat(IScanner *s) {
current = StartState::makeStartState();
scanner = s;
count = 0;
}
void Automat::readChar(char c) {
current->readChar(c, this);
}
I do not know what causes this. do i need to declare things in an interface? Why does it want to convert the arguments?
Thank you all in advance.
Both headers try to include each other, which is impossible.
Luckily, neither class definition needs the full definition of the other. Each only deals with pointers to the other, for which only a declaration is needed. So replace
#include "Automat.h"
with
class Automat;
and likewise for State.
IMO, I would do that preprocessor stuff in the main file, and just define in each header file one variable, so you know that it's included only once. Also you could do that in "StdAfx.h" if given.
This is just a header mess, please be sure to include it only once. #pragma once may help also.
Related
I am currently very new to c++, i have started learning how to use pointers in a path finding algorithm.
I am having an issue with calling a function within a class that is derived from a base class.
The specific piece of code causing issue is:
FreeTile *tempPointer = new FreeTile();
cout<<tempPointer->getFree()<<endl;
mapp[i][j] = tempPointer;
when i call getFree (which returns a boolean value) i get the error:
undefined reference to Tile::getFree(). Tile being the base class.
The header for FreeTile is:
#ifndef FREETILE_H
#define FREETILE_H
#include "Tile.h"
class FreeTile:public Tile
{
public:
FreeTile();
virtual ~FreeTile();
void setParent(FreeTile* par);
int getF();
int getG();
int getH();
void setF(int in);
void setG(int in);
void setH(int in);
FreeTile* getParent();
protected:
private:
int F;
int G;
int H;
bool free;
};
Tile header is:
#ifndef TILE_H
#define TILE_H
class Tile
{
public:
Tile();
virtual ~Tile();
bool getFree();
void setFree(bool bo);
protected:
private:
bool free;
};
#endif // TILE_H
#endif // FREETILE_H
Finally the cpp file for Tile:
#include "Tile.h"
#include <iostream>
using namespace std;
bool free;
Tile::Tile()
{
cout<<"Constructor Called"<<endl;
}
Tile::~Tile()
{
//dtor
}
bool getFree(){
return free;
}
void setFree(bool bo){
free = bo;
}
If you need more code or if im missing something blatant feel free to shame me as much as you like :P
Thanks in advance.
On a side note, can you initiate a private variable in a constructor such as free = true as when doing this it states the variable is private.
In the Cpp file rename "bool getFree()" to
"bool Tile::getFree()"
In your implementation the function is just a regular c gloabl function.
In the fixed version it is the class function implementaion of the function you declare in the header file
Also
1st in your Tile you have a private variable "bool free"
in the cpp file you have a global variable "bool free"
this is confusing.
Probably want to delete the one you declared in the cpp file.
Want a deeper explanation?
Yeah! my 1st answer!
Deeper Explanation:
the function you declared in the Class Tile is not defined (just declared) because you didn't add "Tile::" before the function definition in the cpp file (i.e you didn't define a scope).
The function you wrote in the cpp file is both defined and declared in the cpp file, so only functions written after it in the cpp file can call it (works same a c).
Probably when you wrote the function it didn't know that "free" was, right? because it was not a class function. so you added the global "bool free" but that is a completely different variable.
Glad to help!
don't forget to mark this as answered!
I am writing a simple banking program with derived classes and I am running into a Multiple definition of <method name> error when including parent class.
Keep in mind that I just started coding in C++ yesterday, and moving over from Java/PHP, handling headers/definitions is a bit confusing for me. Please correct anything you see wrong!
Here is a sample of my files/code:
Files
Account.h
Account.cpp (Super)
ChequingAccount.cpp (Child)
SavingsAccount.cpp (Child)
The error is reproduce-able when including the parent class (Account.cpp) into any file. I have reduced my code by a lot, but it should give you an idea of how I am handling inheritance.
To clarify, when I #include the child classes to any file (ChequingAccount.cpp) works fine, and inherited functions work as expected. However, when I #include the parent class (Account.cpp) breaks the compiler with the Multiple definition of <method name> error for all methods.
Again, I am not sure if this is the proper way to do it, but this is what I understand from tutorials I have found.
Code
Account.h
#ifndef ACCOUNT_H
#define ACCOUNT_H
class Account
{
protected:
double m_balance;
public:
Account(double balance); // Constructor.
virtual ~Account(); // Destructor.
// Accessor Methods.
double getBalance() const;
// Mutator Methods.
virtual void withdrawFunds(double amount);
void depositFunds(double amount);
};
#endif
Account.cpp (Superclass)
#include "Account.h"
Account::Account(double balance = 0)
{
m_balance = balance;
}
Account::~Account()
{
// TODO: Delete this data structure...
}
double Account::getBalance() const
{
return m_balance;
}
void Account::withdrawFunds(double amount)
{
m_balance -= amount;
}
void Account::depositFunds(double amount)
{
m_balance += amount;
}
ChequingAccount.cpp (Child)
#include "Account.h"
class ChequingAccount: public Account
{
public:
ChequingAccount(int id, int userId, double balance) : Account(id, balance){};
void withdrawFunds(double amount)
{
// Override parent method.
}
};
Any help would be greatly appreciated! Thank you!
When you #include "some file.cpp", you are directing the compiler to copy the contents of that cpp file to that point in the program. This will create two compiled versions of your "some file" which will lead to "Multiple Definitions."
First of all, "identical" functions declared in base class and sub-class will not cause multiple definition error.
Here is just one example and explanation aiming to help you understand my point:
main.cpp
class father{
void fun();
}
void father::fun(){}
class son : public father{
void fun();
}
void son::fun(){}
int main()
{
return 0;
}
You compile it, and definitely no multiple definition error. In Java, we define functions within classes. In C++, only inline functions are defined within classes and others are declarations, which can be declared whatever times you like. See the definition syntax : father::fun son::fun. These actually define two different functions, one is in father and the other is in son. So there are no multiple definition error. Once more, in class declarations you can only define inline functions and can only declare non-inline functions. So there are on multiple definition errors at all. This just aims to help you understand it in a grammar way.
BTW, if compiler failed to inline, there would be no multiple definition error too because even though you define inline functions in header files and include the files anywhere, inline functions are of internal linkage.
I compiled your codes and got different errors regarding your defined constructors. Anyway, including cpp files using "include" means you don't get the point of implementation file and interface file.
You need to declare the child's method as a member of the child class explicitly in the child's .cpp file as well. See below:
ChequingAccount.cpp (Child)
#include "Account.h"
class ChequingAccount: public Account
{
public:
ChequingAccount(int id, int userId, double balance) : Account(id, balance){};
void ChequingAccount::withdrawFunds(double amount)
{
// Override parent method.
}
};
You already have void Account::withdrawFunds(double) defined when you define void ChequingAccount::withdrawFunds(double).
Try virtual void ChequingAccount::withdrawFunds(double)
The virtual keyword is similar to overriding in Java.
In short, you should not include a cpp file.
The reason you get a multiple definition error actually has nothing to do with class inheritance.
Consider a simple example:
add.h:
#ifndef __ADD_H_
#define __ADD_H_
int add(int a);
#endif
add.cpp:
#include "add.h"
int add(int a) { return a + 1; }
main.cpp:
#include "add.h"
int main() { return add(-1); }
The way C++ dealing with #include directive is simply to copy-paste the included file and replace the #include line. So if we expand the above files manually, we will get something like:
add.cpp:
#ifndef __ADD_H_
#define __ADD_H_
int add(int a);
#endif
int add(int a) { return a + 1; }
main.cpp:
#ifndef __ADD_H_
#define __ADD_H_
int add(int a);
#endif
int main() { return add(-1); }
which will work just fine. (We are allowed to have multiple declarations of a function)
However, if you decide to include the .cpp file instead of the .h file like the code below:
main.cpp:
#include "add.cpp" // notice here
int main() { return add(-1); }
And if you expand it as we just did:
add.cpp:
#ifndef __ADD_H_
#define __ADD_H_
int add(int a);
#endif
int add(int a) { return a + 1; }
main.cpp:
#ifndef __ADD_H_
#define __ADD_H_
int add(int a);
#endif
int add(int a) { return a + 1; }
int main() { return add(-1); }
You will see the code includes multiple definitions of the function add, one of which is in add.cpp and the other one is in main.cpp. When linking these two files together (each .cpp file is compiled separately using a compiler and then linked together using a linker), the linker will be confused by two definitions of add and doesn't know which one to use, so it will start to complain.
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();
}
I want to compile the Rigi source code but I get some error while compiling:
adt/object.h: At global scope:
adt/object.h:35:18: error: ‘class RigiObject RigiObject::RigiObject’ is inaccessible
adt/chararray.h:51:13: error: within this context
make: *** [cl_arcflags.o] Error 1
Here our two files.
object.h:
#ifndef OBJECTH
#define OBJECTH 1
#include <stdio.h>
#ifndef STREAM_H
#include <iostream>
#endif
#ifndef __STRING_H
#include <string.h>
#endif
#ifndef __STDLIB_H
#include <stdlib.h>
#endif
#ifndef _CCHEADER_H_
#include "CCheader.h"
#endif
extern char* indent_line(int);
class RigiObject;
typedef RigiObject* ObjectPtr;
#define Oberr(a) fprintf(stderr,"ERROR :: Generic Object Routine Called :: %s\n","a");
class RigiObject {
public:
RigiObject() {/*Oberr(RigiObject)*/;}
~RigiObject() {/*Oberr(~RigiObject)*/;}
// Routines that are really described by the Derived Classes
virtual int Printout(int) const
{Oberr(printout); return (int) 0;}
virtual unsigned int Hash() const
{Oberr(hash); return (unsigned int) 0; }
virtual RigiBool isEqual(void* a) const
{Oberr(isEqual); a = NIL;
(void) abort();
return (RigiBool) RigiFalse;}
virtual void Delete_class(ObjectPtr)
{Oberr(delete_type);}
virtual void* Create_class();
virtual void* Duplicate_class();
};
#endif
and chararray.h:
#ifndef CHARARRAYH
#define CHARARRAYH
#ifndef ARRAYOBIDH
#include "array.h"
#endif
#ifndef CHARTYPEH
#include "chartype.h"
#endif
class CharArray;
typedef CharArray* CharArrayPtr;
class CharArray : public Array {
int slot;
public:
// Routines to initialize and destroy the class.
CharArray(unsigned int size = CLTN_DEFAULT_CAPACITY);
CharArray(const CharArray&);
~CharArray();
// Functions that are Required to Use this Class as an Object
// .... all routines the same as in Class Array.......
// Routines that are required by a Collection class and derived classes
// of Collections. [See Array Class for these routines.]
virtual unsigned int size() const {return slot;}
// .... all routines the same as in Class Array.......
// Routines specific to this class
void operator=(const CharArray&);
RigiBool operator==(const CharArray&) const;
void Create(char*);
void Create(char*,int);
void Create(int, char*);
void Add(char*);
void Add(CharType&);
void Addob(RigiObject& ob)
{Array::Add(slot++,&ob);}
void Append(char*);
char* Concat(char);
int FindIndex(char*);
char* Remove()
{return ((CharTypePtr)Array::Remove(--slot))->string();}
ObjectPtr Pop()
{return (Array::Remove(--slot));}
ObjectPtr Look(int i)
{return (Array::At(i));}
void Empty();
virtual unsigned int Size() const
{return slot;}
char* Peek();
char* At(int);
};
#endif
What's wrong with the code?
Assuming that the type RigiBool in the declaration RigiBool operator==(const CharArray&) const; is not defined in one of the headers "array.h" "chartype.h" I think you should include the header containing definition of the type, and just to be sure the "object.h" too.
For cases where a header file uses values of class type variables (not pointers and references) it is recommended to include the headers that contain the class definition. Otherwise a simple forward declaration should be enough.
The types RigiBool, RigiObject and ObjPtr are not available in chararray.h: you need to include object.h (plus whatever else defines RigiBool if CCHeader.h doesn't) -- similarly for RigiBool and RigiFalse in object.h
// somewhere at the top of chararray.h
#include "object.h"
Note: if you define virtual member functions in RigiObject, you should declare the destructor virtual as well
Note: You already have include guards in the #included headers, no need to put them around the #include directives -- doing otherwise indicates (falsely in your case) that you are doing conditional compiling
//chararray.h
#ifndef CHARARRAYH
#define CHARARRAYH
#include "array.h"
#include "chartype.h"
...
//object.h
#ifndef OBJECTH
#define OBJECTH
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include "CCheader.h"
...
It's hard to say from the little information but I would assume RigiBool is a derived class of RigiObject? When you now reference RigiBool in chararray.h it has to know the RigiObject base class but the RigiObject also needs to know about RigiBool. So you can't declare the base class without knowing the derived RigiBool. Try if forward declaring RigiBool in object.h helps to break the cycle.
In C++, I have a problem with circular dependencies / incomplete types. The situation is as follows:
Stuffcollection.h
#include "Spritesheet.h";
class Stuffcollection {
public:
void myfunc (Spritesheet *spritesheet);
void myfuncTwo ();
};
Stuffcollection.cpp
void Stuffcollection::myfunc(Spritesheet *spritesheet) {
unsigned int myvar = 5 * spritesheet->spritevar;
}
void myfunc2() {
//
}
Spritesheet.h
#include "Stuffcollection.h"
class Spritesheet {
public:
void init();
};
Spritesheet.cpp
void Spritesheet::init() {
Stuffcollection stuffme;
myvar = stuffme.myfuncTwo();
}
If I keep the includes as shown above, I get the compiler error
spritesheet has not been declared in Stuffcollection.h (line 4 in
the above). I understand this to be due to a circular dependency.
Now if I change #include "Spritesheet.h" to the Forward
Declaration class Spritesheet; in Stuffcollection.h, I get the
compiler error invalid use of incomplete type 'struct Spritesheet'
in Stuffcollection.cpp (line 2 in the above).
Similarly, if I change #include "Stuffcollection.h" to class
Stuffcollection; in Spritesheet.h, I get the compiler error aggregate
'Stuffcollection stuffme' has incomplete type and cannot be defined
in Spritesheet.cpp (line 2 in the above).
What can I do to solve this problem?
You should include Spritesheet.h in Stuffcollection.cpp
Just use forward declaration in the header file not the cpp file, that solves the circular dependency of the header file. The source file has no circular dependency actually.
Stuffcollection.cpp needs to know the complete layout of class Spritesheet(because you dereference it), So you need to include the header which defines the class Spritesheet in that file.
From your previous Q here, I believe that class Stuffcollection is used in the class declaration of Spritesheet header file and hence the above proposed solution.
Use this form for your nested includes:
Stuffcollection.h
#ifndef STUFFCOLLECTION_H_GUARD
#define STUFFCOLLECTION_H_GUARD
class Spritesheet;
class Stuffcollection {
public:
void myfunc (Spritesheet *spritesheet);
void myfuncTwo ();
};
#endif
Stuffcollection.cpp
#include "Stuffcollection.h"
#include "Spritesheet.h"
void Stuffcollection::myfunc(Spritesheet *spritesheet) {
unsigned int myvar = 5 * spritesheet->spritevar;
}
void Stuffcollection::myfuncTwo() {
//
}
Spritesheet.h
#ifndef SPRITESHEET_H_GUARD
#define SPRITESHEET_H_GUARD
class Spritesheet {
public:
void init();
};
#endif
Spritesheet.cpp
#include "Stuffcollection.h"
#include "Spritesheet.h"
void Spritesheet::init() {
Stuffcollection stuffme;
myvar = stuffme.myfuncTwo();
}
General rules I follow:
Don't include an include from an include, dude. Prefer forward declarations if possible.
Exception: include system includes anywhere you want
Have CPP include everything it needs, not relying upon H recursively including it files.
Always use include guards.
Never use pragma
Spritesheet.h doesn't need to include Stuffcollection.h, since no Stuffcollection is used in the class declaration of Spritesheet. Move that include line to Spritesheet.cpp instead and you should be fine.