I have a class "board" that I am trying to put a deque member in. I wrote the code with an int object for the deque and everything worked fine, so I think it is a problem with setting the Template for the custom class, but I have never done this in C++.
board.h:
#ifndef __board_h__
#define __board_h__
using namespace std;
#include <deque>
#include "noble_card.h"
class board;
class board
{
public: deque<noble_card> line;
public: board();
public: ~board();
};
#endif
board.cpp:
#include <deque>
#include "noble_card.h"
board::board() {
deque<noble_card> line;
}
board::~board() {}
I think I may have a problem with the construction method here, as deque is erroring out on so many things I am having trouble tracking it down.
noble_card.h:
#include <string>
#ifndef __noble_card_h__
#define __noble_card_h__
#include "board.h"
class noble_card
{
public: string name;
public: int id;
public: int vp;
public: noble_card(int _vp);
public: ~noble_card();
};
#endif
noble_card.cpp:
#include "noble_card.h"
noble_card::noble_card(int _vp) {
this->vp = _vp;
}
noble_card::~noble_card() {
}
Now, the problem comes when I try to push elements onto this deque, i have a for loop like such:
board b;
for (unsigned i = 0; i < 12; i++) {
noble_card nc(i);
b->line.push_back( nc );
}
I keep getting assignment operator could not be generated, copy constructor could not be generated, and std::deque : 'noble_card' is not a valid template type argument for parameter '_Ty' (board.h). I am assuming this is because I haven't templated my classes and overridden the copy/constructor methods to tell the deque how to sort/remove/alloc/copy this type of class. I'm basically just trying to get a custom c++ class to be used in a deque and it is a lot more complicated than C# and other standard libraries I've used where you just push it on there and it takes care of it.
EDIT:
#ifndef __noble_card_h__
#define __noble_card_h__
using namespace std;
class noble_card {
public: char* name;
public: int id;
public: int vp;
public: noble_card(char* _name, int _id, int _vp) : name(_name), id(_id), vp(_vp) {}
};
#endif
Setting up noble_card.h this way seems to satisfy the requirements for the copy/alloc/constructor for deque. I still don't fully understand it as it seems to be shorthand, so if anyone could expand on line 10 I'd much appreciate it. For now This change has me moving forward.
Small fix of your immediate problem:
Your variable b is not a pointer and the operator->
b->line.push_back(nc);
will therefore not work. You have to use the operator.
b.line.push_back(nc);
C++ is not C# (mini code review)
You write that you are coming from C#. There are a lot of stylistic differences between the two languages that you should be aware off. I don't know C#, but here is a 2nd take on your code, taking care of the sorest points (I'm commenting out the header inclusions as it doesn't work on the online compiler I use)
// noble_card.h
#include <string>
class noble_card
{
public: // single section of public stuff (are you sure you don't need private data?)
std::string name; // never do: "using namespace std;" in a header!
int id;
int vp;
noble_card(int _vp);
// compiler-generated default constructor is just fine here
};
// noble_card.cpp
noble_card::noble_card(int _vp): vp(_vp) {} // initialize member in initializer-list
// board.h
// #include "noble_card.h"
#include <deque>
class board
{
public: // single section of public stuff (are you sure you don't need private data?)
std::deque<noble_card> line; // never do: "using namespace std;" in a header!
// compiler generated default constructor and destructor are just fine here
};
// board.cpp (not necessary for your current impl)
// #include "board.h" // takes care of "noble_card.h"
// main.cpp
int main()
{
board b;
for (unsigned i = 0; i < 12; ++i) {
b.line.emplace_back(i); // C++11 allows you to construct-in-place
}
}
Live Example.
You should Google this site to get in-depth explanations of the points that I write in the above code behind the // comments.
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.
just started to learn c++.I'm trying new things in c++ on thing i wanted to try is to access a class from another class and change its instances and print its instance on screen.
I would like to know 2 things 1)whats wrong with my code 2)where should i declare class declarations (in main file or class definition file?)
here is the error log -
'object::carrier' uses undefined class 'sub'
'cout': is not a member of 'std'
'cout': undeclared identifier
this is what i came up with-
source.h
#include <iostream>
#include <vector>
#include "stuff.h"
int main()
{
object spoon(3);
spoon.get();
}
stuff.cpp
#pragma once
#include <vector>
class object;
class sub;
class object
{
private:
std::vector <sub> thing;
public:
object(int n);
void get() const;
};
class sub
{
private:
int num;
public:
void set_num(int n);
};
stuff.cpp
#include <vector>
#include "stuff.h"
// methods for object
object::object(int n)
{
sub carrier;
carrier.set_num(n);
}
void object::get() const
{
std::cout << carrier.num;
}
// methods for sub
void sub::set_num(int temp_num)
{
num = temp_num;
}
thanks
In your object class, specifically object::get definitions, you use the variable carrier without it being in scope.
When you declare the variable sub carrier in your constructor, it is only accessible in the same scope, that is, inside the constructor. Once your program leaves the scope, the variable carrier is deallocated (deleted).
You must add the variable sub carrier as a member to your class like so:
class object
{
private:
sub carrier
// other stuff
}
Edit:
I so you edited your question.
You must either replace cout with std::cout because cout is part of the c++ standard library. Alternatively, a less verbose option would be to add using namespace std; at the top of every .cpp file. This basically tells the compiler that you can use the namespace std without explicitly saying it. But don't do it for .h files. It's not a good idea.
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;
}
This is my base class Shape.h
#ifndef Shape_H
#define Shape_H
#include <iostream>
using namespace std;
class Shape
{
protected:
string name;
bool containsObj;
public:
Shape();
Shape(string, bool);
string getName();
bool getContainsObj();
double computeArea();
};
#endif
Shape.cpp
#include "Shape.h"
Shape::Shape(string name, bool containsObj)
{
this -> name = name;
this -> containsObj = containsObj;
}
string Shape:: getName()
{
return name;
}
bool Shape::getContainsObj()
{
return containsObj;
}
and this is my sub class. Cross.h
#ifndef Cross_H
#define Cross_H
#include <iostream>
#include "Shape.h"
using namespace std;
class Cross: public Shape
{
protected:
int x[12];
int y[12];
public:
Cross();
double computeArea();
};
#endif
Cross.cpp
#include "Cross.h"
Cross::Cross()
{
for (int i = 0; i < 12; i++)
{
this -> x[i] = 0;
this -> x[0] = 0;
}
}
Shape and Cross are in different files, but inside the same folder. The weird thing is when i compile this, errors that i have never seen before came up such as "In function 'ZN5CrossC1Ev', undefined reference to Shape::Shape(),'ZN5CrossC1Ev', undefined reference to Shape::Shape(), undefined reference to WinMain#16".
I tried to do some debugging myself. When i remove the Cross constructor, it works fine. But i definitely need it. Can anyone explain this to me?
You didn't define the default constructor but you declared it Shape();. The only constructor you defined is the one with string and bool parameters Shape(string, bool);.
adding
Shape::Shape()
{
}
or removing
Shape();
will fix it.
For future debugging read the error more carefully, it explains exactly whats wrong:
undefined reference to Shape::Shape()
You've declared a default constructor for Shape, but not defined it anywhere. The default constructor for Cross uses it implicitly to initialise its base class.
You options are:
Define the constructor, if you want Shape to be default-constructible;
Otherwise, remove the declaration and get Cross to initialise Shape with the other constructor.
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.