What is the best way of declaring my header files if I want to have the following connections in my C++ code, just so that I don't get the 'include nested too deeply error'?
On my edge class, I have some functions that need to return a Node object. Same for the Edge class, I have functions that need to return a Node object. However the compiler disallow me to have this nested loop thing.
Node.h
#ifndef _NODE_h__
#define __NODE_h__
#include "Edge.h"
public:
Node();
~Node();
void setName(string);
string getName();
void addEdge(Edge*);
vector<Edge* > getEdges() { return _edges; };
};
#endif
Edge.h
#ifndef _EDGE_h__
#define __EDGE_h__
#include "Node.h"
class Edge
{
public:
Edge();
Edge(bool);
~Edge();
bool hasBeenSeen() { return _seen; };
void reset() { _seen = false; }; // resets seen param to false
Node* getSource() { return _source; };
Node* getTarget() { return _target; };
void setSource(Node* source) { _source = source; };
void setTarget(Node* target) { _target = target; };
};
#endif
As others have suggested, use header guards. But also try forward declaring the classes in question. You may also have to work with pointers (rather than values) in at least one of your classes, but without seeing the code, we can't tell.
So edge.h should like something like:
#ifndef EDGE_H
#define EDGE_H
class Node; // forward declaration
Node functionB();
#endif
Note that you will have to define your function in a separate C++ file which then #includes "node.h".
If all this seems very complicated, then you should try simplifying your design. It is probably not necessary for nodes and edges to know about each other — a one way dependency should suffice.
And lastly, names containing double-underscores are reserved in C++ — you are not allowed to create such names in your own code.
Edge.h
#ifndef EDGE_H_INCLUDED
#define EDGE_H_INCLUDED
class Node;
class Edge
{
int edge_num;
public:
Edge(int i) : edge_num(i) { };
Node memberB();
};
#include "Node.h"
Node Edge::memberB() { Node n(edge_num); return n; }
Node functionB() { Node n(2); return n; }
#endif /* EDGE_H_INCLUDED */
Node.h
#ifndef NODE_H_INCLUDED
#define NODE_H_INCLUDED
class Edge;
class Node
{
int node_num;
public:
Node(int i) : node_num(i) { };
Edge memberA();
};
#include "Edge.h"
Edge Node::memberA() { Edge e(node_num); return e; }
Edge functionA() { Edge e(1); return e; }
#endif /* NODE_H_INCLUDED */
Note that I have forward declared the classes 'Edge' and 'Node' before the other header is included, so that by the time the function or member function is defined, the class it returns is also defined.
The problem with your include guards is that they don't match!
You test for _SOMETHING (one underscore) and then if not found you define __SOMETHING (two underscores); these two should match else the include guard does not work!
As others have noted avoid starting things with underscores as those are reserved for libs and OS.
This is prevented by using either pragma guards or #pragma once (the latter if your compiler supports it).
To use pragma guards, simply do this:
#ifndef SOME_IDENTIFIER
#define SOME_IDENTIFIER
// ... code ...
#endif
Make sure to change SOME_IDENTIFIER for every header file. Usually people make it NAME_OF_HEADER_H; make sure you change both instances of the identifier if you change one.
Also if you do this, make sure any #includes you do are inside the pragma guards.
If you just want to use #pragma once and your compiler supports it, you just have to add
#pragma once
to the top of your header file.
On another note, consider moving the definition of the functions functionA and functionB to their own .cpp files and keeping just the prototype in the .h files, so you don't get linker errors.
Related
Good morning.
I'm trying to implement a graph in c++ with nodes and edges memorized as lists. I'm italian so: graph/Grafo , edge/Arco , node/Nodo , listEdges/ListaArchi, listNodes/ListaNodi.
This is my code:
Grafo.h
#ifndef GRAFO_H_
#define GRAFO_H_
#include "ListaNodi.h"
class Grafo {
public:
Grafo();
virtual ~Grafo();
void leggiGrafo(std::string nomeFile);
void aggiungiNodo(std::string nomeNodo);
private:
std::string nomeGrafo;
ListaNodi nodi;
};
#endif /* GRAFO_H_ */
Grafo.cpp
#include "Grafo.h"
Grafo::Grafo() {
}
Grafo::~Grafo() {
}
void Grafo::aggiungiNodo(std::string nomeNodo) {
}
void Grafo::leggiGrafo(std::string nomeFile){
}
Arco.h
#ifndef ARCO_H_
#define ARCO_H_
#include <string>
#include "Nodo.h"
class Arco {
public:
Arco();
virtual ~Arco();
Arco *next;
std::string style;
std::string color;
private:
Nodo primo;
Nodo secondo;
};
#endif /* ARCO_H_ */
Arco.cpp (Here is where the problem is:
Arco.cpp:10:12: error: no matching function for call to 'Nodo::Nodo()'
#include "Arco.h"
Arco::Arco() {
// TODO Auto-generated constructor stub
next = NULL;
}
Arco::~Arco() {
// TODO Auto-generated destructor stub
}
Nodo.h
Other problem here:
Nodo.h:15:2: error: extra qualification 'Nodo::' on member 'Nodo' [-fpermissive]
#ifndef NODO_H_
#define NODO_H_
#include <string>
#include "ListaArchi.h"
class Nodo {
public:
Nodo::Nodo(std::string nome);
virtual ~Nodo();
void setColore(std::string colore);
ListaArchi listaArchi;
Nodo *next;
private:
std::string colore;
std::string nome;
std::string label;
};
#endif /* NODO_H_ */
Nodo.cpp
#include "Nodo.h"
#include <string>
Nodo::Nodo(std::string nome) {
this->nome = nome;
this->colore = "white";
next=NULL;
}
Nodo::~Nodo() {
}
Arco.h
Other problem here:
ListaArchi.h:16:2: error: 'Arco' does not name a type
#ifndef LISTAARCHI_H_
#define LISTAARCHI_H_
#include "Arco.h"
class ListaArchi {
public:
ListaArchi();
virtual ~ListaArchi();
Arco arco;
};
#endif /* LISTAARCHI_H_ */
ListaArchi.cpp
#include "ListaArchi.h"
ListaArchi::ListaArchi() {
}
ListaArchi::~ListaArchi() {
}
ListaNodi.h
#ifndef LISTANODI_H_
#define LISTANODI_H_
#include "Nodo.h"
class ListaNodi {
public:
ListaNodi();
virtual ~ListaNodi();
Nodo nodo;
};
#endif /* LISTANODI_H_ */
ListaNodi.cpp
#include "ListaNodi.h"
ListaNodi::ListaNodi() {
nodo = NULL;
}
ListaNodi::~ListaNodi() {
}
Could anyone help me with these problems?
You have multiple problems. One is that in your ListaNodi class use the Nodi class to declare an object nodo. That will use the default constructor of Nodi, but you haven't declared or defined one. Only a constructor taking a string.
The simple solution for the above is to create a Nodi default constructor, i.e. a constructor taking no arguments.
Another problem is in the ListaNodi constructor implementation, where you do
nodo = NULL;
Here you treat nodo as a pointer, which it isn't. The solution to this is to remove that line, and instead use a constructor initializer list:
ListaNodi::ListaNodi()
: nodo{}
{
}
Of course, that requires you to have fixed the first problem above, by creating a default constructor.
Furthermore inside the class definition of Nodo you declare the (non-default) constructor using scoping, which is not needed.
Plain
Nodo(std::string nome);
is all you need.
Finally you have the problem with a circular header-file dependency, where ListaArchi depends on Arco which depends on Nodo which depends on ListaArchi. You need to find a way to break that header-file dependency circle. The simplest way to break such a circle is to use pointers somewhere, and forward declaration of the type instead of including the header file.
It seems that you are making lists, which means you can very easily break the header-file circular dependency by making the "nodes" in the list classes being pointers, something which they probably should be from the beginning. That will actually solve the two first problems I mentioned as well.
Then the ListaArchi.h header file could look like this:
#ifndef LISTAARCHI_H_
#define LISTAARCHI_H_
class Arco; // Forward declaration instead of header file inclusion
class ListaArchi {
public:
ListaArchi();
virtual ~ListaArchi();
Arco* arco; // Declares as a pointer
};
#endif /* LISTAARCHI_H_ */
And ListaNode.h should look like
#ifndef LISTANODI_H_
#define LISTANODI_H_
class Nodo; // Forward declaration instead of header file inclusion
class ListaNodi {
public:
ListaNodi();
virtual ~ListaNodi();
Nodo* nodo; // Declare as a pointer
};
#endif /* LISTANODI_H_ */
Finally your ListaNodi constructor makes more sense with the NULL assignment, but I suggest you still use construction initializer lists:
ListaNodi::ListaNodi()
: nodo{nullptr}
{
}
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 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.
Note: I have found the issue with how my Xcode was compiling the below and it appears unrelated to the topic discussed herein. When I have more details I will provide them here.
I recommend voting to close my question as "too localized" since it was an Xcode problem, unrelated to the c++ code itself. Many thanks for the help all the same as I did learn from the answers.
The below question (now answered and resolved) was caused by a confusing exclusion of a file from the Xcode target, thus there were no compiler errors even though the file had problems.
I have a pure virtual interface and want to define its factory method, which returns a subclass of this interface. This works fine:
struct MyVirt{
...all virtual stuff
};
class SubVirt; //forward declaration allows factory:
MyVirt*CreateClass(){
return new SubVirt;
}
Update: Some of the comments say that forward declare is not enough to achieve the above, but that's not correct. You can accomplish the above fine without the full definition of the SubVirt class.
Now, what I want to do is have a custom constructor that takes arguments. As such:
MyVirt*CreateClass(){
return new SubVirt(arg 1, etc);
}
The problem is that a class forward declaration is no longer sufficient. It needs to see the class definition or its header. This means I can either move the factory method to the file where SubVirt is defined, or I have to include that file in the above file, which creates a circular dependency.
Is there a way to forward declare the custom constructor instead? That would make it all much simpler.
Your CreateClass function looks odd, you miss () in function definition. Should be like this:
MyVirt* CreateClass()
{
return new SubVirt(arg 1, etc);
}
When return a pointer, compiler needs to know the concrete type and constructor, so forward declare is not enough.
What you could do is:
in header file: forward declare SubVirt and CreateClass function
cpp file: include MyVirt.h and define CreateClass function
Separate declaration from implementation, like everyone does.
MyVirt.h:
struct MyVirt{
...all virtual stuff
};
MyVirt.cpp:
#include "MyVirt.h"
Implementation of MyVirt
SubVirt.h:
#include "MyVirt.h"
struct SubVirt : MyVirt {
...all SubVirt stuff
};
SubVirt.cpp:
#include "SubVirt.h"
Implementation of SubVirt
Factory.h:
struct MyVirt;
MyVirt *CreateClass();
Factory.cpp:
#include "SubVirt.h"
MyVirt *CreateClass() { return new SubVirt() }
This can be accomplished by separating the declaration and implementation.
The key here is to put the definition/implementation above the includes. Suppose you want to separate the classes A and B create two files like the following:
A.hpp
#ifndef A_HPP
#define A_HPP
struct B; // fwd. decl.
struct A {
int v;
A(int v) {
this->v = v;
}
B* createB();
};
#include "B.hpp"
A* B::createA() {
return new A(v);
}
#endif A_HPP
B.hpp
#ifndef B_HPP
#define B_HPP
struct A; // fwd. decl.
struct B {
int v;
B(int v) {
this->v = v;
}
A* createA();
};
#include "A.hpp"
B* A::createB() {
return new B(v);
}
#endif // B_HPP
main.hpp
#include <A.hpp>
#include <B.hpp>
#include <iostream>
int main(int argc, char *argv[]) {
A a(42);
std::cout << a.createB()->createA()->v << std::endl;
return 0;
}
You are of course free to move the implementation into a cpp file instead. This is only the basic recipe which shows how circular dependencies can be solved even for templated classes and functions.
http://codepad.org/IsBzQANX
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.