I have a dynamic array-based class that I'm calling MyList, that looks as follows:
#ifndef MYLIST_H
#define MYLIST_H
#include <string>
#include <vector>
using namespace std;
template<class type>
class MyList
{
public:
MyList();
~MyList();
int size() const;
type at() const;
void remove();
void push_back(type);
private:
type* List;
int _size;
int _capacity;
const static int CAPACITY = 80;
};
#endif
I also have a another class that I'm calling User that I want to include an instance of MyList as a private data member. User looks like this:
#ifndef USER_H
#define USER_H
#include "mylist.h"
#include <string>
#include <vector>
using namespace std;
class User
{
public:
User();
~User();
private:
int id;
string name;
int year;
int zip;
MyList <int> friends;
};
#endif
When I try to compile I get an error in my user.cpp file:
undefined reference to MyList::Mylist()
I find this odd because MyList is completely unrelated to user.cpp, which only contains my User constructor and destructor.
Make sure that you write both the declaration and the definition of your template class into the header (define MyList in the header not in a .cpp file)
The reason is that you did not provide MyClass<int> constructor definition. Unfortunatelly in C++ you cannot divide template class definition by declaring methods in header file and defining them in the implementation. At least if you want to use it in other modules. So in your case User class needs to have MyClass<int>::MyClass() definition right now. There are two ways to do it:
(the easiest one) provide constructor definition right in place:
MyClass() {
...
} or
add method definition in MyClass.h after class definition like that:
template<class type> MyList<type>::MyList() {
...
}
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.
Having trouble understanding why I'm getting an 'undeclared identifier' error when I've made sure to include the header file that has the declaration of the class I'm making a vector of.
#pragma once
#include <vector>
#include "Member.h"
class Party {
private:
std::vector<Member> members;
public:
Party();
int get_party_size();
void add_member(Member new_member);
Member& get_member(int num);
};
Here's "Member.h"
#pragma once
#include <vector>
#include <string>
#include "Party.h"
class Member
{
private:
int hp;
bool is_stunned;
bool is_alive;
public:
Member();
~Member();
int get_hp();
bool get_is_stunned();
bool get_is_alive();
void take_damage(int amt);
void stun();
virtual void turn(std::vector<Party>& parties, int my_party, int my_member_number);
virtual std::string get_class_name();
};
Pretty new to the language, so sure I'm missing something obvious.
You have circular dependency between Member and Party
Remove the line
virtual void turn(
std::vector<Party>& parties,
int my_party,
int my_member_number);
in Member and remove the #include "Party.h" in Member.h
Instead think along the lines that a Party is just a collection of Members so there is no need for an individual Member to know about the container
So after input from #some-programmer-dude you could also solve it by adding a forward declaration in your Member.h instead of including the Party.h
class Party;
class Member { ... }
I have two classes: SessionCardsMode and SetOfCards. SessionCardsMode takes in its constructor pointer to object of SetOfCards. When I try to create dynamically new SessionCardsMode object in SetOfCards method initializing it with this pointer I get information: "Cannot initialize type 'SessionCardsMode' with rvalue of type 'SetOfCards*'". It looks like I haven't proper constructor, but I have provided it. I don't know why it doesn't work. The problem is in SetOfCards::getSessionCards method in the first line of it. I've found that if I try to create the same object in body of class SessionCardsMode using identical statement everything works fine, but if I try to make it out of class I get the error.
//////////////////////////////SesionCardsMode.h
#pragma once
#include "Card.h"
#include "SetOfCards.h"
class SessionCardsMode
{
protected:
SetOfCards* m_setData;
std::forward_list<Card*> m_sessionSet;
public:
explicit SessionCardsMode(SetOfCards* set) : m_setData(set) {};
virtual Card* getCard();
//allows making combination of set setup by mixing classes that derives
//from ModeOfSet
void addAndShuffle(const SessionCardsMode* mode);
};
///////////////////////////////SetOfCards.h
#pragma once
#include "Card.h"
#include "SessionCardsMode.h"
class SetOfCards
{
private:
std::vector<Card> m_cardSet;
std::string m_setName;
public:
SetOfCards()=default;
explicit SetOfCards(std::string setName);
template<typename Iter>
SetOfCards(Iter begin, Iter end, std::string setName);
SessionCardsMode* getSessionCards(std::vector<CreatorAndInitVal> creators);
};
////////////////////////////////////////SetOfCards.cpp
#include "SetOfCards.h"
SessionCardsMode* SetOfCards::getSessionCards(
std::vector<CreatorAndInitVal> m_sessionCardsCreators)
{
SessionCardsMode* sessionCards=new SessionCardsMode(this); // error here
return sessionCards;
}
I don't understand why you don't get an error when you declare the constructor of SessionCardsMode (when you are compiling SetOfCards.cpp) - as far as I can see, at that point, SetOfCards is not defined.
Anyway, the solution to your problem is not to #include any of the headers in other headers, but to declare (not define) the other classes. So:
//////////////////////////////SesionCardsMode.h
#pragma once
class Card;
class SetOfCards;
class SessionCardsMode
{
protected:
SetOfCards* m_setData;
std::forward_list<Card*> m_sessionSet;
public:
explicit SessionCardsMode(SetOfCards* set) : m_setData(set) {};
...
};
///////////////////////////////SetOfCards.h
#pragma once
class Card;
class SessionCardsMode;
#include <vector> // You need this
#include <string>
class SetOfCards
{
private:
std::vector<Card> m_cardSet;
std::string m_setName;
public:
SetOfCards()=default;
explicit SetOfCards(std::string setName);
...
};
////////////////////////////////////////SetOfCards.cpp
#include "SetOfCards.h" // This should always be first
#include "..." // You'll probably need some more here.
SessionCardsMode* SetOfCards::getSessionCards(
std::vector<CreatorAndInitVal> m_sessionCardsCreators)
{
SessionCardsMode* sessionCards=new SessionCardsMode(this); // Error should be fixed
return sessionCards;
}
I have this annoying error in my program.
"Vehicle" is the Base class.
"Bicycle" extends this class.
#ifndef BICYCLE_H
#define BICYCLE_H
#include "Vehicle.h"
#include <string>
#include <iostream>
using namespace std;
//Template class which is derived from Vehicle
template<typename T>
class Bicycle: public Vehicle
{
public:
Bicycle();
Bicycle(int, int, string, int);
~Bicycle();
//Redefined functions inherited from Vehicle
void move(int, int); // move to the requested x, y location divided by 2
void set_capacity(int); // set the capacity value; can't be larger than 2
};
Above is the Bicycle.h file (I do not have .cpp file for this class)
#ifndef VEHICLE_H
#define VEHICLE_H
#include "PassengerException.h"
#include <string>
#include <iostream>
using namespace std;
//ADD LINE HERE TO MAKE IT A TEMPLATE CLASS
template<typename T>
class Vehicle
{
public:
Vehicle(); //default contstructor
Vehicle(int, int, string, int); // set the x, y, name, and capacity
virtual ~Vehicle(); //destructor; should this be virtual or not???
//Inheritance - question #1; create these functions here and in Bicycle class
string get_name(); // get the name of the vehicle
void set_name(string); //set the name of the vehicle
void print(); // std print function (GIVEN TO YOU)
//Polymorphism - question #2
virtual void move(int, int); // move to the requested x, y location
virtual void set_capacity(int); // set the capacity value
//Operator overloading - question #3
Vehicle<T> operator+(Vehicle<T> &secondVehicle) const;
//Exceptions - question #4
T get_passenger(int) throw(PassengerException); // get the passenger at the specified index
void add_passenger(T) throw(PassengerException); // add passenger and the current passenger index
void remove_passenger() throw(PassengerException); // remove a passenger using current passenger index
protected:
int x_pos;
int y_pos;
string name;
int capacity;
T *passengers;
int current_passenger;
};
Above is the Vehicle.h file. I do not have .cpp for this either.
Also, what do the ifndef define endif mean? Do I have to use those? Are they required?
And, do their names have to be formatted like that?
class Bicycle: public Vehicle
Vehicle is a template, so you need this:
class Bicycle: public Vehicle<T>
The #ifndef and #define and #endif are called header guards and are used to prevent your header file from being included more than once, causing things (classes) to be declared more than once.
The ifndef define and endif are necessary for the actual base files, i.e. the c++ files themselves. Yes they are required, if you plan to use those functions and variables accordingly. Yes, their names have to be formatted that way, that's the way directives or in some cases flags must be formatted.
You have to put #endif at the end of your header files. These are so called define guards to prevent multiple inclusion of header files. See more at Include guard.
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.