I have this subclass Pirate.cpp and I want its mov function to access an array from main.
This array is basically the map (To check if it already has ship, dock and to access the array to change the object's (pirate ship) location from map[1][1] to map[1][2].
This map is a two-dimensional array of sea objects that each one can hold a ship with the pointer.
Ship is parent class of pirate (I have other subclasses I will do dynamic_cast before inserting Pirate to the Ship pointer).
I have an error code: 'Map' , 'Place' was not declared in this scope which I understand.
So basically how do I deal with this scope issue? Is there an alternate approach?
Pirate.cpp
#include "pirate.h"
#include "Sea.h"
void Pirate::mov()
{
MAP[1][2]->(*place)=MAP[1][1]->(*place)
MAP[1][2]->(*place)=NULL
}
Sea.h
#ifndef SEA.H
#define SEA.H
#include "ship.h"
class Sea
{
private:
bool hasShip;
bool isDock;
protected:
Ship *place = NULL;
public:
bool gethasShip() const {return hasShip;}
bool getisDock() const {return isDock;}
void sethasShip(bool i) {hasShip = i;}
void setisDock(bool i) {isDock = i;}
};
#endif
main
#include <iostream>
#include <vector>
#include <string>
#include "Ship.h"
#include "Sea.h"
#define SIZE 100
using std::cout;
using std::vector;
extern Sea Map[SIZE][SIZE];
int main()
{
Sea Map[SIZE][SIZE];
}
extern makes a declaration instead of a definition. It only says that somewhere the object is definied.
You need to have Sea Map[SIZE][SIZE]; in your main.cpp and extern Sea Map[SIZE][SIZE]; in other files from which you access the array.
There are a couple of things you could do:
You could make the Map a global variable by declaring it outside of main(), and use extern to reach it from within Pirate::mov.
You could also create a singleton, but that suffers from some of the same problems as globals.
A better solution is a class that contains the Map and the Pirates. When you construct your Pirates you could have each Pirate a reference to the Map.
Related
I am trying to make functions repository. I have created four files:
Function.hpp, Function.cpp, FunctionsRepository.hpp, FunctionsRepository.cpp
I want to keep pointers to functions in vector of pointers.
//FunctionsRepository.hpp
#ifndef FUNCTIONSREPOSITORY_HPP
#define FUNCTIONSREPOSITORY_HPP
#include <vector>
using namespace std;
class FunctionsRepository {
private:
static vector<double *> pointerToFunctions;
public:
static void addFunction(double * wsk);
};
#endif
//FunctionRepository.cpp
#include "FunctionsRepository.hpp"
void FunctionsRepository::addFunction(double * wsk) {
pointerToFunctions.push_back(wsk);
}
//Functions.hpp
#ifndef FUNCTIONS_HPP
#define FUNCTOINS_HPP
#include "FunctionsRepository.hpp"
int constFunction(int numberOfVehicles);
void linearFunction();
void stepFunction();
#endif
//Funcctions.cpp
#include "Functions.hpp"
double constFunction(double numberOfVehicles){
return numberOfVehicles/2;
}
double (*funcConstant)(double) = constFunction;
//ERROR HERE
FunctionsRepository::addFunction(funcConstant);
I want to add new functions to program as easily as its possible and use it leater in other parts of program.
But I dont get it. Why i am getting this error. The addFunction() method is static, that means I can use it in other classes or parts of program. Vector is static to make sure that is the only one copy for whole program.
Use function wrapper. std::function can stores callable objects. So, your code will contain something like this:
class FunctionsRepository {
private:
// void() - function prototype
static std::vector<std::function<void()>> pointerToFunctions;
public:
static void addFunction(std::function<void()> wsk)
{
pointerToFunctions.push_back(wsk);
}
};
for more information consult official documentation: http://en.cppreference.com/w/cpp/utility/functional/function
I solved It. I received an error because I was calling the FunctionsRepository::addFunction(funcConstant); expression out of any scope. I just created new function to execute this command and thats all.
I keep getting error: undefined reference to 'Company::budget'.
My method is set so as to take the value of company's (any created) budget and subtract Employees' salary from it. I keep getting this problem. Tried both pointers and let's say "normal calling". Ok, there's the code snippet: (rest of it works)
company.h
#include <iostream>
#include <cstdlib>
#include <list>
#include <vector>
#include "employee.h"
using namespace std;
class Company
{
public:
Company* comp;
void hire(Employee& emp, float putSalary);
void fire(Employee& emp);
void endOfMonth(Company& comp);
Company(float);
// static float moneyamount;
private:
static float budget;
vector <Employee>* Employees;
};
company.cpp
void Company::endOfMonth(Company& comp)
{
for (iterat=0; iterat < Employees->size() ; iterat++)
{
cout << (*Employees)[iterat].fullName << endl;
cout << (*Employees)[iterat].getSalary() << endl;
comp.budget = comp.budget - (*Employees)[iterat].getSalary();
}
}
You are missing the definition of the static class data member. Add the following line to the file company.cpp:
float Company::budget;
Static class members variables are static over all instances of a class. So if you have two instances of one class, they share the static variable. Also, these variables are also valid even when there is no instance of the class. So, static member functions may use static member variables. That is the reason why they must defined somewhere outside the class in the object file.
You define it and reserve the necessary space for it in memory at the top level of you .cpp file:
float Company::budget;
I got a issue in GraphicsList.cpp in Qt 5.4
#include "GraphicsList.h"
GraphicsList::GraphicsList()
{
_DesignLayerList=new QList<WorkSystem::GraphicShape>();
}
void GraphicsList::Draw(){
for(int i=this->_DesignLayerList->count();i>=0;--i){
WorkSystem::GraphicShape shapeObject=(WorkSystem::GraphicShape)_DesignLayerList[i];
// WorkSystem::GraphicShape shapeObject=_DesignLayerList[i];
shapeObject.Draw();
}
}
QQQ/GraphicsList.cpp:9: error: no matching conversion for C-style cast
from 'QList' to 'WorkSystem::GraphicShape'
WorkSystem::GraphicShape shapeObject=(WorkSystem::GraphicShape)_DesignLayerList[i];
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
My GraphicList.h
#ifndef GRAPHICSLIST_H
#define GRAPHICSLIST_H
#include "GraphicShape.h"
class GraphicsList
{
public:
GraphicsList();
~GraphicsList();
void Draw();
private:
QList<WorkSystem::GraphicShape> *_DesignLayerList;
};
#endif // GRAPHICSLIST_H
my GraphicShap.h
#ifndef GRAPHICSHAPE_H
#define GRAPHICSHAPE_H
#include <QDebug>
#include <QPainter>
namespace WorkSystem {
class GraphicShape
{
public:
GraphicShape();
~GraphicShape();
QColor _penColor;
virtual void Draw();
};
}
#endif // GRAPHICSHAPE_H
My GraphicShape.cpp
#include "GraphicShape.h"
#include <QDebug>
WorkSystem::GraphicShape::GraphicShape()
{
_penColor=Qt::white;
}
void WorkSystem::GraphicShape::Draw(){
qDebug()<<"DrawDrawDrawDraw";
}
WorkSystem::GraphicShape::~GraphicShape()
{
}
Please give me any suggestion.
shapeLine.h
#ifndef SHAPELINE_H
#define SHAPELINE_H
#include <QDebug>
#include "GraphicShape.h"
namespace WorkSystem {
class shapeLine : public GraphicShape
{
public:
shapeLine();
~shapeLine();
protected:
void Draw();
};
}
#endif // SHAPELINE_H
shapeLine.cpp
...
The problem appears to be a bit of a misuse of pointers. If you look at the declaration for your _DesignLayerList member:
QList<WorkSystem::GraphicShape> *_DesignLayerList;
You are not declaring an actual QList instance. Instead, you are declaring a pointer to a QList. Thus when you use _DesignLayerList[i], you aren't actually trying to look into the list, but instead doing pointer arithmetic to look up another QList instance, which is not what you are expecting.
Instead, you should declare your member variable without the star, meaning will be an actual instance of a QList rather than a pointer to a QList:
QList<WorkSystem::GraphicShape> _DesignLayerList;
This will then function as expected. I would also recommend reviewing your understanding of the difference between pointers and values, as this is a fundamental of C++. In modern C++, it is recommended to avoid the use of raw pointers as much as possible and instead use smart pointers, references, and value types as they are generally more appropriat and safer.
An alternative, if you insist on using pointers, is to perform a lookup by first de-referencing the pointer so you are referring to the QList instance it points to. However, I would not recommend this as it adds overhead and additional complexity for no benefit:
shapeObject = (*DesignLayerList)[i]
As an example of the problems common to using raw pointers like this: while you create the QList instance, you never actually delete it and as such this code leaks memory.
While trying to make a simple game, I've run in to a circular dependency problem.
I searched on the internet and found that forward declaring could fix it, but... Both of my classes depend on a static value.
Is there any easy way to fix, perhaps to forward declare the static values, or do I have to rewrite the core of my game?
2ND EDIT: Looks like I was wrong, the error's still there even after removing almost everything:
main.cpp:
#include "App.h"
//Start the app
int main(int argc, char* args[]){
App App;
return App.on_execute();
}
App.h:
#ifndef APP_H
#define APP_H
#include "Object.h"
class App
{
public:
//Runs when the program starts
int on_execute();
};
#endif // APP_H
App.cpp:
#include "App.h"
int App::on_execute(){
return 0;
}
Object.h:
#ifndef OBJECT_H
#define OBJECT_H
#include <string>
#include <vector>
#include <stdio.h>
#include <SDL.h>
#include <math.h>
#include "Entity.h"
class Object
{
public:
Object(int character, int x, int y, std::string name, SDL_Color color, bool blocks);
//Object vector
static std::vector<Object*> objects;
};
#endif // OBJECT_H
Object.cpp:
#include "Object.h"
std::vector<Object*> Object::objects;
Object::Object(int character, int x, int y, std::string name, SDL_Color color, bool blocks){
}
Entity.h:
#ifndef ENTITY_H
#define ENTITY_H
#include "Object.h"
#include <sdl.h>
class Entity : public Object
{
public:
Entity(int character, int x, int y, std::string name, SDL_Color color, bool blocks, int hp, int power, int defense);
};
#endif // ENTITY_H
Entity.cpp:
#include "Entity.h"
Entity::Entity(int character, int x, int y, std::string name, SDL_Color color, bool blocks, int hp, int power, int defense) : Object(character, x, y, name, color, blocks){
}
I think the design of your code may need to be reworked.
First of all, I'd really discourage you from using non-primitive, non-trivial class statics where possible, whether class static or global static. Non-trivial static classes will have an explicit constructor call before main, and will need to register a destruction to be called after main. The relative ordering of these things is undefined. Worse, if you have a library structure later such that the assembly from the same .cpp file shows up twice, weird things can happen where two copies of the object get constructed, but the same one is destroyed twice.
Second, some of the information is unclear. For example, you claim that the Map class has a static member of type Map. I really don't think this is possible; the static Map member will also have an object of type map, and so on. Similarly with the vector of Objects declared inside Object. Maybe in both these cases you mean inside the file Map.cpp or Object.cpp, as opposed to literally inside the class?
Third, be clear on what forward declaration gives you. It makes the compile aware that something exists, nothing more. It lets you have pointers and references to that type. You cannot create an object or even declare a member variable of a forward declared type, because the compiler doesn't know the size of the forward declared object. You can't use its methods because the compiler doesn't know they exist.
Fourth, you didn't talk about your header files at all. It's only a circular dependency if Map.h requires Object.h, and vice versa. Two header files can't both include each other. On the other hand, the implementation is in Map.cpp and Object.cpp, both of these files can include both Map.h and Object.h. However, personally I prefer to avoid having mutually dependent classes.
What I'd probably suggest is that a Map should own the Objects present on that map. The pattern right now with Map accessing this global is not a good one. Instead of having objects be a global, make std::vector objects a member of the Map class. Notice that if you decide to have multiple Maps later, this works much better, each Map will own the Objects located on that map. The current design doesn't work well if there's more than one Map.
You can then implement move_to as a method not of Object, but rather of Map. Map::move_to(i, dx, dy) moves the ith Object.
So far I've looked up most of the typical solutions for cases of this error and yet non of them seems to work with my code. I'm using dev-c++
The structure of problematic class is following.
m.hh
#ifndef M_H
#define M_H
#include "z.hh"
#include <iostream>
#include <string>
using namespace std;
class M: public Z
{ /* this line is marked by the compiler as errorneous */
void m1();
void m2();
};
#endif
m.cpp
#include <iostream>
#include <string>
#include "m.hh"
using namespace std;
void M::m1() {/*bla bla*/};
void M::m2() {/*bla bla*/};
}
EDIT:
z.hh
#ifndef Z_H
#define Z_H
#include "m.hh"
#include <iostream>
#include <string>
using namespace std;
class Z;
static Z* s(string g, string i);
#endif
z.cpp
#include "z.hh"
#include <iostream>
#include <string>
class Z
{
public:
string i;
string g;
void set_i(string im) {i = im;}
string get_i() {return i;}
string get_g() {return g;}
virtual void m1()=0;
virtual void m2()=0;
Z* s(string g, string i) {
Z * z;
if(g=="m"){
M * z = new M;
}
}
};
Thanks!
Remove #include "m.hh" from z.hh to fix the circular include.
THE PROBLEM
You cannot derive from an incomplete type, which is what Z is in m.hh.
Upon deriving from a type the compiler must know the definition of said type. Just imagine you are trying to call a derived member function from Z on an object of type M, how would the compiler know if such call is a valid construct without knowing if Z actually declares such member?
And, a more relevant point, how would M be able to initialize Z without knowing what Z is?
THE SOLUTION
Move the definition of class Z to z.hh, and leave the definitions of its member functions in z.cpp (the same way you have split up M across m.hh, and m.cpp).
Well, the z.cpp file is actually a class declaration and should be a header file. A forward decalaration is only sufficient when you deal with pointers to that class, but not for inheriting from one (the compiler does need to know z's class layout for that).
The z.hh is not really needed, and the function declaration in it is not what you think (it's not a member function declaration). You can delete it and rename z.cpp to z.hh.
Ok, the exchange with #Luchian Grigore made me realize what you probably wanted and why you had "two z.hh". Z is to produce an M, but M inherits from Z, so there is a circular dependency. In C/C++ the way to break such a circle is to limit what one of the classes needs to know from the other: In order to declare a member function s that produces a pointer to a new M Z's class declaration only needs a typename M, not a the whole class declaration. So just a forward declaration (class M;) that introduces the type name M into the declaration of Z is enough; if the pointer to the M object is returned as a pointer to the base, Z, M's name is not even needed at all when Z is declared.
The definition of the factory function (be it file static or a member function) needs, if it is to produce an M, M's complete declaration though. That would be in a seaparate cpp file, which would include a complete header with M's full declaration.