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}
{
}
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.
The problem I am facing is somehow related to "loop inclusion" or "incompleted class"
I have 2 classes:
ControllerManager, this class is declared as Singleton, this class has a object of AuxController.
AuxController, this class has a function that needs to get the instance of ControllerManager
The problem is: when compiling source code, it fails with error "incomplete type" or "invalid type"
Is there any way to fix this problem?
or is there any other way to redesign code structure?
Source code
ControllerManager.h
#ifndef CONTROLLERMANAGER_H
#define CONTROLLERMANAGER_H
#include "auxcontroller.h"
class ControllerManager
{
/* This class is defined as Singleton class */
private:
/* 1. define a private static instance */
static ControllerManager *inst;
public:
/* 2. define a public static accessor */
static ControllerManager *getInstance(){
/* 3. do lazy initialization */
if(!inst){
inst = new ControllerManager();
}
return inst;
}
protected:
/* 4. Define all accessors to be protected */
ControllerManager();
~ControllerManager();
/* property */
private:
int m_code;
public:
int getCode()
{
return m_code;
}
void setCode(int _code)
{
m_code = _code;
}
/* below code causes fail of compilation */
public:
AuxController m_auxcontroller;
};
#endif // CONTROLLERMANAGER_H
ControllerManager.cpp
#include "controllermanager.h"
/* 5. initialize static variable */
ControllerManager *ControllerManager::inst = 0;
ControllerManager::ControllerManager()
{
m_code = 15;
}
ControllerManager::~ControllerManager()
{
delete inst;
}
AuxController.h
#ifndef AUXCONTROLLER_H
#define AUXCONTROLLER_H
/* if do NOT include controllermanager.h with below line,
* and declare ControllerManager class as a forward declaration:
*
* class ControllerManager;
*
* compiler will stop due to "incomplete type"
*/
#include "controllermanager.h"
class AuxController
{
public:
AuxController();
void setControllerCode(int code);
};
#endif // AUXCONTROLLER_H
AuxController.cpp
#include "auxcontroller.h"
AuxController::AuxController()
{
}
void AuxController::setControllerCode(int code)
{
/* if do NOT include controllermanager.h ,
* and declare ControllerManager class as a forward declaration in the header file:
*
* class ControllerManager;
*
* compiler will stop due to "incomplete type" at this line
*
*/
ControllerManager::getInstance()->setCode(code);
}
main.cpp
#include "controllermanager.h"
int main(int argc, char *argv[])
{
ControllerManager *ctlMng = ControllerManager::getInstance();
ctlMng->setCode(10);
return 0;
}
Do not include "controllermanager.h" inside auxcontroller.h, but do include it inside auxcontroller.cpp.
In general you should not include header files by other header files if it can be avoided. Use forward declaration instead. But do include all required header files from cpp files.
The problem consists into a cycle dependency.
In order to solve that problem: use forward declaration and include all needed header only in the cpp (compilation-unit) file.
In ControllerManager.hpp:
class AuxController;
class ControllerManager {
// ...
public: AuxController* m_auxcontroller;
};
// Remember to not use m_auxcontroller in the header file, JUST declaration are allowed.
Note: you have to use pointers or references to the forwarded class, so remember to initialize them correctly.
In the ControllerManager.cpp:
#include "ControllerManager.hpp"
#include "AuxController.hpp" // In Cpp file include everything you need.
// ...
The same in the class AuxController.
In the AuxController.hpp:
// You dont need header of other file in this case.
class AuxController {
// ...
};
In AuxController.cpp:
#include "AuxController.hpp"
#include "ControllerManager.hpp"
// ...
one of my class variables that is a pointer to another class is giving a error of no type. can figure it out after a few days thinking about it, anyone see a mistake? also for some reason the line
r->setright(NULL)
crashes the program
#include "gridnode.h"
#include "grid.h"
#include "basenode.h"
class grid
{
public:
grid();
void print();
protected:
gridnode *head;//error of no type here
};
#endif // GRID_H
and my node class
class gridnode:public basenode
{
public:
char mark;
gridnode *l, *r, *u, *d;
gridnode(){
l->setleft(
r->setright(NULL);//crashes
u->setup(NULL);
d->setdown(NULL);
}
//set and get functions
protected:
};
any help greatly apreciated.
one of my class variables that is a pointer to another class is giving a error of no type.
gridnode has not been defined yet when you try to use it. That can happen if you have circular references in your .h files, for instance. Since you are just declaring a pointer, you can use a forward declaration instead:
#ifndef GRID_H
#define GRID_H
// there should be no include of grid.h here
// move the gridnode.h and basenode.h includes to grid.cpp instead
class gridnode; // forward declaration
class grid
{
public:
grid();
void print();
protected:
gridnode *head;
};
#endif // GRID_H
also for some reason the line
r->setright(NULL)
crashes the program
Inside the gridnode constructor, you are calling methods on l, r, u, and d pointers that have not been initialized to point at anything. You are invoking undefined behavior by calling methods on them. You probably meant to set the pointers themselves to NULL instead, eg:
gridnode(){
l = NULL;
r = NULL;
u = NULL;
d = NULL;
}
Or:
gridnode() :
l(NULL),
r(NULL),
u(NULL),
d(NULL)
{
}
Trying to pass a parent class object to a child class object so that the child class object has control over the parent class object's methods.
This is however resulting in header related issues.
I've tried forward declaring one of the classes but it seems whatever class is declared first always has trouble reading from the class declared below.
Both errors refer to Device' constructor where try to call dm's hello world method, they are:
Use of undefined type 'DeviceManager'
Left of '->HelloWorld' must point to class/struct/union/generic type
...
//main.cpp
#include "parent.h"
void main()
{
cout << "Created DeviceManager\n";
DeviceManager* deviceManager = 0;
deviceManager = new DeviceManager;
cout << "Giving DeviceManager a device\n";
deviceManager->p = new Device(deviceManager);
cout << "Giving Device a reference to DevicenManager\n";
deviceManager->Share();
}
...
class DeviceManager;
class Device
{
public:
Device(DeviceManager* manager)
{
dm = 0;
this->dm = manager;
this->dm->HelloWorld();
}
DeviceManager* dm;
};
//device manager
class DeviceManager
{
public:
DeviceManager()
{
p = 0;
}
void HelloWorld()
{
//if this calls we know the child has control over the parent.
cout << "Hello World";
}
Device* p;
};
Yes.
To solve circular dependencies with class member and function declarations, you can forward-declare a class:
class A;
class B {
A *a;
};
class A {
B *b;
};
To define class member functions that access members of the other class, you must define the function after the other class has been defined:
class B;
class A {
public:
void f(B &arg);
};
class B {
public:
void g(A &arg);
};
void A::f(B &arg) {
arg.g(*this);
}
void B::g(A &arg) {
arg.f(*this);
}
Usually, in a C++ project, you wouldn't even encounter this problem: You would put function definitions, i.e. implementations, into .cpp files, while putting the class definitions into header files. Class forward declarations, if neccesary, could be put into their own header files that are included by all headers that need them.
A full example of how you would split the above code into multiple files:
a.cpp
#include "a.h"
#include "b.h"
void A::f(B &arg) {
arg.g(*this);
}
b.cpp
#include "b.h"
#include "a.h"
void B::g(A &arg) {
arg.f(*this);
}
a.h
#ifndef _A_H_
#define _A_H_
#include "forward_declarations.h"
class A {
public:
void f(B &arg);
};
#endif //_A_H_
b.h
#ifndef _B_H_
#define _B_H_
#include "forward_declarations.h"
class B {
public:
void g(A &arg);
};
#endif //_B_H_
forward_declarations.h
#ifndef _FORWARD_DECLARATIONS_H_
#define _FORWARD_DECLARATIONS_H_
class A;
class B;
#endif //_FORWARD_DECLARATIONS_H_
As a general rule of thumb, if you need to forward-declare a class, you might have misdesigned something and should think about whether there is a better way (but there also are perfectly valid use cases that require class forward declarations).
If you don't understand my #ifndef, #define and #endif preprocessor lines: These are header guards, and should be used with all files that are included somewhere else, exception you know precisely what you're doing. Believe me. You'll regret ommiting one.
If your problem is cyclic dependancy, like this:
// DeviceManager.h
#include "device.h"
class DeviceManager
{
DeviceManager(Device& device) {}
};
// Device.h
#include "DeviceManager.h"
class Device
{
Device(DeviceManager& manager) {}
};
You can solve the problem be forward declaring one of the classes, and passing the object by pointer.
// Device.h
//#include "DeviceManager.h"
class DeviceManager;
class Device
{
Device(DeviceManager* manager) {}
};
I'm doing a small program, just to play with classes.
And I've made two classes, a and b.
I want to be able to access a in b and vice versa.
This is what I got so far:
#ifndef A_HH_
#define A_HH_
#include <string>
class b;
class a
{
private:
string aString;
b* bClass;
public:
a(){aString = "A";}
string getString(){return aString;}
string getBString(){return bClass->bString;}
};
#endif /* A_HH_ */
and b:
#ifndef B_HH_
#define B_HH_
#include <string>
class a;
class b
{
private:
string bString;
a* aClass;
public:
b(){bString = "B";}
string getString(){return bString;}
};
#endif /* B_HH_ */
I want to be able to access the pointer not just store it.
How can I do that?
The problem is that you use the bClass pointer in class a, for that you need the definition of class b. In this case this can be solved by simply including b.hh in a.hh. This simple solution will work as you're only declaring an a pointer (but don't access it) in the class b. A forward declaration is not enough, because it doesn't actually tells the compiler anything more than that the class b exist.
Oh, and you need to change the bClass->bString in a::getBString to bClass->getString(), as b::bString is private. And of course create an actual instance of b and assign it to bClass.
In short, to access members of a struct or a class, you need to meet two conditions:
the accessing element (class, method, ...) must have access "rights" to the referenced member
the definition of the struct/class must be available.
To overcome 1. you can either make the member public, or declare the accessing class or method as friend, or better use a getter method.
To overcome 2., you need to include the header of the referenced class.
You might use templating:
for a:
#ifndef A_HH_
#define A_HH_
#include <string>
#include "b.h"
class a
{
private:
string aString;
b* bClass;
public:
a()
{
aString = "A";
bClass = new b<a>;
}
string getString(){return aString;}
string getBString(){return bClass->getString();}
};
#endif /* A_HH_ */
and for b:
#ifndef B_HH_
#define B_HH_
#include <string>
template <typename T>
class b
{
private:
string bString;
T* aClass;
public:
b()
{
bString = "B";
aClass = new T;
}
string getString(){return bString;}
string getAString(){return aClass->getString();}
};
#endif /* B_HH_ */
This removes the circular dependency