Working on a collaborative project (was hoping two would be easier than one - how wrong was I...?)
Basically, what we're trying to do is a bit like this:
class first
{
first(int * num);
};
class second
{
second(first * frst);
first * frt;
};
first::first(int * num)
{
}
second::second(first * frst)
{
frt = frst;
}
There is a bit of an issue though, we can't include our Core.h file, since that contains includes to the files we're already including (there is sense somewhere there). Short version is, we're having to do something a bit more like this:
#ifndef PLAYERSTRUCTURE
#define PLAYERSTRUCTURE
// DO NOT INCLUDE CORE IN THIS FILE
class Core;
struct PlayerMem
{
int cid;
int y, x, z;
};
class Player
{
public:
Player::Player(Core * coar);
Player::Player(void);
Player::~Player(void);
};
#endif
The Core class is declared but not defined, will this cause issues if we try to access it from within the Player class, using Core->GetSomething() etc?
Thanks
You're forwarding declaration. It's OK.
When you can use Core->GetSomething() without any compilation error then it means class Core is defined and it's not an incomplete type. So, there is no issue to use it. Just make sure you're passing a valid pointer to Core when constructing Player.
Note: In your code you're passing a pointer to a class type not a reference.
Related
I am creating an Arduino library which takes two constructors for a personal project of mine, but for some reason I keep getting an error which is specific to types, first let me show you how the structure goes. so here is my files:
this is the header file:
#ifndef iGA_H
#define iGA_H
class iGA {
public:
getParameters(int soundA[], int soundB[], int parentId[]);
private:
int _soundA[];
int _soundB[];
int _parentId[];
}
the cpp file:
#include <iGA.h>
iGA::getParameters(int soundA[], int soundB[], int parentId[])
{
_soundA = soundA;
_soundB = soundB;
_parentId = parentId;
}
And this is how im pretty much calling the constructor in the sketch, within the setup() function:
#include <iGA>
iGA iga;
void setup() {
iga.getParameters(r, r1 , r2);
}
and here is the error:
In file included from /home/bargros/Dropbox/iGA__NewBild/iGA__NewBild.ino:34:0:/home/bargros/Arduino/libraries/iGA/iGA.h:10:58: error: ISO C++ forbids declaration of 'getParameters' with no type [-fpermissive]getParameters(int soundA[], int soundB[], int parentId[]);
I know the error has something to do with argument types or maybe im calling the constructor wrongly but I also tried calling it like this:
iGA iga = getParameters(etc,etc,etc);
im relatively new to c++ and im a little clueless as to what this error is telling me. Does anyone have any sort of idea of why this happens?
I believe two issues:
Issue 1: Your function should return something right? you may want to set it as void if it just meant to assign the parameters to the private members (it is a setter and not a get in your case). Add void in the proper locations both inside the class and when you write its definition.
Issue 2: I think that you can't send an array[] as a parameter. And I assume that you already know the size. You need, instead, to send a pointer that points to the first element of the array along with the size of the whole array. Then, once you receive the parameters, for every private member, you create a new array with the size received (or just fill the private member directly) and fill the values by iterating the received array using the pointer received.
Edit: I just checked and passing int array[] should be fine. So fixing issue one will fix your problem. See here for further documentation.
In C++ you have to be explicit that a function doesn't return anything, which you do by saying it returns void:
getParameters(int soundA[], int soundB[], int parentId[]);
needs to be
void getParameters(int soundA[], int soundB[], int parentId[]);
and
iGA::getParameters(int soundA[], int soundB[], int parentId[])
needs to be
void iGA::getParameters(int soundA[], int soundB[], int parentId[])
I am working on a little game engine but I got stuck at something. Explanation : I have two classes, cEntity And ObjectFactory :
cEntity
class cEntity:public cEntityProperty
{
Vector2 position;
Vector2 scale;
public:
cEntity(void);
cEntity(const cEntity&);
~cEntity(void);
public:
void init();
void render();
void update();
void release();
};
ObjectFactory
#include "cEntity.h"
#include <vector>
class ObjectFactory
{
static std::vector<cEntity> *entityList;
static int i, j;
public:
static void addEntity(cEntity entity) {
entityList->push_back(entity);
}
private:
ObjectFactory(void);
~ObjectFactory(void);
};
std::vector<cEntity> *ObjectFactory::entityList = new std::vector<cEntity>();
Now I am adding new cEnity to ObjectFactory in cEntity constructor but facing an error related to circular references: for using ObjectFactor::addEntity() I need to define the ObjectFactory.h in cEntity class but it creates a circular reference.
I think your code might have an underlying architectural issue given how you have described the problem.
Your ObjectFactory should be handling the cEntities, which in turn should be unaware of the "level above". From the description of the problem you are having, it implies that you're not sure what class is in charge of what job.
Your cEntitys should expose an interface (i.e. all the stuff marked "public" in a class) that other bits of code interact with. Your ObjectFactory (which is a bit badly named if doing this job, but whatever) should in turn use that interface. The cEntitys shouldn't care who is using the interface: they have one job to do, and they do it. The ObjectFactory should have one job to do that requires it to keep a list of cEntitys around. You don't edit std::string when you use it elsewhere: why is your class any different?
That being said, there's two parts to resolving circular dependencies (beyond "Don't create code that has circular dependencies in the first place" - see the first part to this answer. That's the best way to avoid this sort of problem in my opinion)
1) Include guards. Do something like this to each header (.h) file:
#ifndef CENTITY_H
#define CENTITY_H
class cEntity:public cEntityProperty
{
Vector2 position;
Vector2 scale;
public:
cEntity(void);
cEntity(const cEntity&);
~cEntity(void);
public:
void init();
void render();
void update();
void release();
};
#endif
What this does:
The first time your file is included, CENTITY_H is not defined. The ifndef macro is thus true, and moves to the next line (defining CENTITY_H), before it moves onto the rest of your header.
The second time (and all future times), CENTITY_H is defined, so the ifndef macro skips straight to the endif, skipping your header. Subsequently, your header code only ever ends up in your compiled program once. If you want more details, try looking up how the Linker process.
2) Forward-declaration of your classes.
If ClassA needs a member of type ClassB, and ClassB needs a member of type ClassA you have a problem: neither class knows how much memory it needs to be allocated because it's dependant on another class containing itself.
The solution is that you have a pointer to the other class. Pointers are a fixed and known size by the compiler, so we don't have a problem. We do, however, need to tell the compiler to not worry too much if it runs into a symbol (class name) that we haven't previously defined yet, so we just add class Whatever; before we start using it.
In your case, change cEntity instances to pointers, and forward-declare the class at the start. You are now able to freely use ObjectFactory in cEntity.
#include "cEntity.h"
#include <vector>
class cEntity; // Compiler knows that we'll totally define this later, if we haven't already
class ObjectFactory
{
static std::vector<cEntity*> *entityList; // vector of pointers
static int i, j;
public:
static void addEntity(cEntity* entity) {
entityList->push_back(entity);
}
// Equally valid would be:
// static void addEntity(cEntity entity) {
// entityList->push_back(&entity);}
// (in both cases, you're pushing an address onto the vector.)
// Function arguments don't matter when the class is trying to work out how big it is in memory
private:
ObjectFactory(void);
~ObjectFactory(void);
};
std::vector<cEntity*> *ObjectFactory::entityList = new std::vector<cEntity*>();
Here's my situation. I have a class in which I have defined a vector publicly, as below:
class TrackObjects
{
public:
vector<MovingObj> movingObjects;
...
etc.
It has a constructor and everything. I have a separate .cpp file with some implementations where I'm trying to use that vector and methods on that vector. As one example, it's part of a condition in a function like so:
if (movingObjects.locX >= x1)
...
etc.
It tells me movingObjects is undeclared, and to first use this function. It's not a function, and to my knowledge, I haven't called it like one/tried to use it like one.
Can anyone suggest why I might be getting this error?
EDIT: locX is a public variable in the another class MovingObj. TrackObj is the class that creates the vector for objects MovingObj creates. Sorry, I really should've specified that. Like so:
class MovingObj {
public:
MovingObj(int inId, int inLocX, int inLocY, int inWidth, int inHeight);
int id, locX, locY,width,height;
Based on what you are telling us, the proper way to access locX would be something along the lines of:
TrackObjects objs;
objs.movingObjects[15].locX = 123.45;
Or, maybe:
if(objs.movingObjects[15].locX >= 15)
{
//do something
}
You can also encapsulate your access method in TrackObjects (put this in your TrackObjects.cpp implementation):
bool TrackObjects::testLocX(int pos)
{
if(movingObjects[pos].locX>=15)
return true;
return false;
};
This is an elementary C++ issue. movingObjects is part of an object. Code that is not part of the TrackObjects class can only access movingObjects by specifying which object's movingObjects you wish to access.
if (someobject.movingObjects.size() > 0)
...
Another issue is that to access such an object from another cpp file you will first have to #include the file that contains the class definition.
I'm trying to define a public struct inside a C++ class, and can't figure out how to make it compile. In my header, I have the following:
class AtomUtility
{
public:
struct BoundingBox;
void doWork(struct AtomUtility::BoundingBox bounds);
};
And in the source:
#include"AtomUtility.h"
struct AtomUtility::BoundingBox
{
double xMin, xMax;
};
int main()
{
AtomUtility::BoundingBox *myBox = new AtomUtility::BoundingBox;
myBox->xMin = 0;
myBox->xMax = 10;
AtomUtility *myUtility = new AtomUtility;
myUtility->doWork(*myBox);
delete myUtility;
}
void AtomUtility::doWork(struct AtomUtilty::BoundingBox bounds)
{
//do things...
}
When I attempt to compile this, I get an error: "class "AtomUtility" has no tag member named "BoundingBox".
You've missed the semi-colon after the definition of AtomUtility::BoundingBox and your compiler is getting confused and giving a poor diagnostic.
You're also trying to pass a AtomUtility::BoundingBox* to a function expecting a AtomUtility::BoundingBox
If your compiler gives poor diagnostics it's often useful to try your code on a different compiler. Several are available online, e.g. Comeau, Clang, or a pastebin that compiles, such as http://codepad.org
Quoting https://stackoverflow.com/a/6368118/1483826:
you can only declare pointer or reference to the later class (...). You cannot have objects of later class.
To fix this, you'd need to declare the struct before the class using it as a field.
I am trying to access a method of an object (myEOS.calc(...)) from a method of an object (myPlanet) of another class containing an instance of the first class (static EOS myEOS):
// class in class
class EOS {
public:
static float Y;
float calc(float);
};
float EOS::calc(float x){
return x; // some complicated calculation
}
class Planet {
public:
static EOS myEOS; // want only one instance; cf. below
static void setX(float* X); // must be static; cf. below
};
void Planet::setX(float* X) {
*X = myEOS.calc(*X); // will give an error
}
int main(){
Planet myPlanet;
}
This returns the linking-time error
In function `Planet::setX(float*)':
test.cpp:(.text+0x1a): undefined reference to `Planet::myEOS'
collect2: ld returned 1 exit status
Compiling separately, with -c, the classes and the main program (with an #include in the main file) gives no error; this looks like the key to the solution but I do not see the lock!
Does someone know what the problem is? I hope my intent is clear from what I have, even if there is some fundamental misconception. I thought I somewhat understood classes and reread tutorials but saw no discussion of classes within classes (not nested classes). I was not able to find a similar question on this site (from which I can usually get all the answers I need!) either.
By the way, following somebody else's question, adding explicit constructors (and correctly initialising the EOS in Planet's initialiser list) did not remove the compiler complaint about "undefined reference to Planet::myEOS'" (this done without thestatic` keyword).
Finally, note that Planet::setX needs to be static because a pointer to this method must have a "class-less" signature as it is passed to a function that cannot handle methods/classes:
void (*fun_ptr)(float*) = & (Planet::setX);
This also forces the object myEOS to be static (needs to be accessed from a static function), and anyway the initialisation of EOS objects is expensive.
Thanks a lot for anybody's help!
class Planet {
public:
static EOS myEOS; // want only one instance; cf. below
This code says "Compiler: Somewhere later will be a global EOS myEOS for this class. And the compiler says "ok", and does it's thing, waiting for you to tell it where the global EOS myEOS is.
Then the linker comes along to clean up the compiler's mess, and says "I can't find the myEOS, where'd you place the myEOS?" And displays an error.
You need to add the following lines to a CPP file somewhere:
float EOS::Y;
EOS Planet::myEOS;
Define the static variable.
// class in class
class EOS {
public:
static float Y;
float calc(float);
};
float EOS::calc(float x){
return x; // some complicated calculation
}
class Planet {
public:
static EOS myEOS; // want only one instance; cf. below
static void setX(float* X); // must be static; cf. below
};
void Planet::setX(float* X) {
*X = myEOS.calc(*X); // will give an error
}
// -------------------------
EOS Planet::myEOS;
float Planet::Y /* = <some value> if it makes sense*/;
// -------------------------
int main(){
Planet myPlanet;
}
See 9.4.2 Static Data Members in the standard (98).