Heres my problem, if I pass a variable from class A to class B via function, then in class B pass that variable to other functions for testing then it works fine.
But if I pass the variable from A to B then try assigning it to a variable in class B, it gives the error for no reason
//Globals.h
enum TypeofObject { CIRCLE, SQUARE, RECTANGLE, DIAMOND };
//Object.h
#include "Globals.h"
class Object
{
void Update();
private:
TypeofObject currentObject;
CollisionDetection * gameCollision;
};
//Object.cpp
void Object::Update()
{
//Do stuff here
gameCollision -> testCollision(currentObject);
}
//CollisionDetection.h
#include "Globals.h"
class CollisionDetection
{
public:
void testCollision(TypeofObject currentObject);
private:
void checkObjects(TypeofObject currentObject);
TypeofObject currentObject;
}
//CollisionDetection.cpp
void CollisionDetection::testCollision(TypeofObject curObject)
{
currentObject = curObject; //<- If I have this then it gives access violation error
checkObjects(curObject); //<- Passing it from one function to the next works
//fine but I want to assign it to currentObject so
//it doesnt need to be passed
}
I assume the issue here is that Object::gameCollision has not been initialised. The CollisionDetection::testCollision function is called correctly because you can imagine member functions as regular function taking an extra hidden parameter:
void CollisionDetection_testCollision(CollisionDetection *this,
TypeOfObject curObject);
Given your definition, the function will run correctly up until the point where this is accessed:
currentObject = curObject; // this->currentObject = curObject
The line above is trying to set some memory at an offset from the this object. If this is not correctly initialised, the function will fail with an access violation.
I presume that checkObjects(curObject) does not fail because you are not accessing any of the data members of CollisionDetection in that function.
Related
I am working on a c++ object orientation project. I defined a vector as a private variable in my ListOfShapes class:
vector<Shape*> list_of_shapes = {};
Shape is another class, and below is the header file of it:
class Shape{
private:
string color;//private variable
public:
Shape(string c);//non-default constructor
string getColor();//returns color of the object
virtual void print() = 0;//pure virtual "print" function
};
Shape is the parent class of a class called Rectangle:
class Rectangle:public Shape{
public:
Rectangle(const string &c,double length,double breadth);
void print();
private:
double length, breadth;
};
In the main function I create a ListOfShapes object which contains a function that pushes a pointer (pointing to a Shape object) into the vector I mentioned above. Here is the implementation of the called function:
void ListOfShapes::addShape(Shape* s) {
list_of_shapes.push_back(s);
}
And finally here is the action of calling in the main function:
int main() {
ListOfShapes* list;
Shape* r;
r = new Rectangle( "red",1,1);
list->addShape( r);
return 0;
}
My code compiles fine and even runs if I try to create the same vector (that stores pointers to Shape) inside the main function. The issue happens inside the addShape method, when the push_back method inside the vector class is called, it is using a null pointer for some reason. I've spent hours trying to debbug this issue but I cant seem to find the cause of it.
The error I am getting is:
You are accessing an uninitialized pointer list:
int main() {
ListOfShapes* list;
Shape* r;
r = new Rectangle( "red",1,1);
list->addShape( r); // <-- list is not initialized, thus undefined behavior
return 0;
}
If you look at your debugger output, you see that this has a strange value in the addShape function. This is an indication that the object itself is not valid, and anything done within an invalid object is also invalid.
Simply create a list local object. There is no need for a pointer:
int main() {
ListOfShapes list;
Shape* r;
r = new Rectangle( "red",1,1);
list.addShape( r);
return 0;
}
Also, your Shape class should have a virtual destructor. If you attempted to delete the objects stored in list by iterating through list, the program will invoke undefined behavior due to Shape not having a virtual destructor.
I have a class "A" that take its variables' values from the application's GUI. let us say one of these variables is "X". then, in another class "B", I would like to call this "X" and pass its value to another function.
what I did is that I created an object of class "A" called "objectA" in class "B", and then called the value of "X" as follow:
// class A:
void classA::function1(int gui_value){
x= gui_value;
}
then in the another class:
//class B:
void classB::run(){
.
.
function2(/* I need to pass x here */);
.
.
}
both functions and x are defined in the header file correctly.
what I did is that I created an object of classA (let us say: objectA) in the header file and call the value of "x" in "function2" in "classB" using "objectA" as follow:
//class B:
void classB::run(){
.
.
function2(objectA->x);
.
.
}
Let us say "x" value equals "5", when I debug the value of "x" in function2, it gives me random number everytime i debug. So, I am just guessing that these random values are already exist in the memory, which means the value of "X" is not passed correctly.
I think, although the object is created, however it create a new instance of variable "x" everytime. i.e.: is not taking the value of "x" from classA, it is just create an object of classA with all its variables.
my problem is how to pass the vlaue of "x" that is obtained in classA directly to classB without creating a new instance of its variable ?
Update:
Thanks to doctorlove's answer, my code is now working fine. My problem was in initializing "objectA" after its creation and assigning a value to it. what I was doing is creating the object and passing it directly in "classB". That is why i was getting the random values as it was just a new object which have whatever value in the memory in the time of creation.
It is not clear what you are trying to do. If you have something like this...
class A
{
private:
int X;//ignoring any thing about encapsulation for now
};
class B
{
//...
public:
void DoSomething()
{
A objectA;
//makes objectA another A each time we get here, with X uninitialised
//use objectA.X which has random numbers in
}
};
this will behave similarly to the problem you describe. If you make objectA a member instead and initialise it properly it might do what you want. With class A as before,
class B
{
//...
private:
A objectA;
public:
B()
{
objectA.X = 42;
}
void DoSomething()
{
//use member objectA.X
}
};
EDIT
Clearly in my example I have pulled 42 out of nowhere. If you have a sensible value from the gui, send it to the constructor of B. If it changes you'll need a reference to it instead.
explicit B(int gui_value)
{
objectA.X = gui_value;
}
EDIT2
If you have an existing objectA someplace else, then pass that to the constructor
explicit B(const A & otherA)
: objectA(otherA)
{
}
If that's not possible, your design needs improving. Without any code to look at I cannot help any more.
let's say you got a class A with an private int variable i , and B with and private int variable X,
class A{
private:
int i;
// if you want to use x within A you have to declare the object here
B objectB;
.....
public :
int getI();
int setI();
};
// the second class B
class B(){
private :
int X;
......
public :
int getX();
void setX();
..
};
let'S say you have a main() function
int main (){
A objA;
B objB;
objB.setX(5);//X is now 5
objA.setI(objB.getx()); // i has the value of X which is 5
...
}
Since there is no compile time error on the creation of the objectA, the object is successfully been created.
To pass the variable, instead of using arrow operator use dot(.) operator
y = objectA.X
I'm trying to make a chess program, but I want to be able to implement different AIs in it. Thus I made a abstract AIgeneric class and the derived class AIrandom off of AIgeneric. Then in my chessAI interface, I create a list of the the AIs, and try to call their getNextMove function and run into a segfault. The code is as below:
class AIgeneric {
public:
virtual int getNextMove(int*, const int &) = 0;
}
class AIrandom : public AIgeneric {
public:
AIrandom();
virtual int getNextMove(int*, const int &);
}
class chessAI {
public:
chessAI();
~chessAI();
void setAI();
int getNextMove(int*, const int &);
private:
vector<AIgeneric*> AIlist;
vector<string> names;
int selectedAI;
};
chessAI::chessAI () {
AIrandom randomAI;
AIlist.push_back(&randomAI);
names.push_back("Random AI");
selectedAI = -1;
}
int chessAI::getNextMove(int * board, const int & color) {
return AIlist[selectedAI]->getNextMove(board, color); //segfault on this line
}
It'd be great if anyone could help me on this problem!
Edit: I do set selectedAI to 0 before calling getNextMove.
In this code:
chessAI::chessAI () {
AIrandom randomAI;
AIlist.push_back(&randomAI);
names.push_back("Random AI");
selectedAI = -1;
}
You store a pointer to a local variable into your vector. After the constructor returns that pointer is no longer valid.
Remember that all local variables are stored on the stack, and the stack is reused in other functions. So when you use the pointer in the vector, it now points to some other functions memory and not the one object you declared.
This can be solved in three ways:
Allocate the object on the heap:
AIlist.push_back(new AIRandom);
Not using pointers at all.
Use smart pointers, such as std::unique_ptr.
You call selectedAI = -1; and then AIlist[selectedAI]->.... What do you expect AIlist[-1] to be, other than undefined behavior?
I expect this is because AIlist[selectedAI] is out of bounds. You can confirm this by replacing it with AIlist.at(selectedAI). Keep in mind that this index is -1 immediately after the constructor...
I have a variable, which is a member of one of my classes, that another is in need of, but I'm not sure how to effectively pass the value between them without using a global variable, which is something I'd like to avoid if at all possible. I know I could create an object, but that would invoke the constructor of the originating class which would execute a number of functions and write the needless results to memory, which would be wasteful of system resources.
Is there an easy way to pass this value between the two functions?
Update: The class that is in need of the variable, called no_of_existing_devices. The purpose of class Initialise is to open up a file and count the number of lines of test it contains, and place that number in the variable int no_of_existing_devices, which is then used by the Device::Device() to create an object for each
class Device
{
public:
void view_attribute_list();
void set_attribute();
Device();
};
Device::Device()
{
for (int count = 0; count < no_of_existing_devices; count ++)
{
// Create an object for each iteration, up to a maximum of no_of_existing_devices
}
}
The class of which this variable is a member
class Initialise
{
public:
int no_of_existing_devices;
bool initialisation;
string existing_device_list[100];
void initialise_existing_devices();
Initialise();
};
Initialise::Initialise()
{
no_of_existing_devices = 0;
}
void Initialise::initialise_existing_devices()
{
string line;
ifstream DeviceList;
DeviceList.open("devices/device_list");
while (true)
{
getline(DeviceList, line, '\n');
if (DeviceList.eof())
{
break;
}
++ no_of_existing_devices;
}
DeviceList.close();
DeviceList.open("devices/device_list");
for (int i = 0; i < no_of_existing_devices; i ++)
{
getline(DeviceList, line, '\n');
existing_device_list[i] = line;
}
Device existing_devices[no_of_existing_devices];
!initialisation; // Existing devices are now initialised
}
Okay, from what I understand:
You don't want to have a global
You don't want to have a static
You don't want to introduce a dependency between Device and Initialise
There is one other option, assuming something owns Device and Initialise, move the no_of_existing_devices up to there, then construct both Device and Initialise with a reference to this variable...
In a similar circumstance I was just passing the pointer to the member --- I had to invoke a member function then, so it was a pointer to the member function, http://www.parashift.com/c++-faq-lite/pointers-to-members.html
It's a bit messy, but it works :-).
If the variable in the originating class can hold a value without an instance of the class I would assume that the variable is static. If not create a public static member of the class. And use it in the target class.
Something like:
// .h file
class A
{
public:
static int a;
}
// .cpp file
int A::a = 123;
// .cpp file of class B
void B::foo()
{
cout << A::a;
}
If it is a class attribute (internal variable), then you can obtain a reference through a get method. Otherwise, you can use the friend keyword on the class you want to access the attribtue from the other For example, if you declare friend class B; on class A, the attributes of the class B will be accessible on the class A.
I suggest you use the first method in order to maintain your code OO pure ;)
Edit: of course, if you access through a reference there are no resources wasted :)
Edit 2: use a static method on Initialise class that returns the no_of_existing_devices and call Initialise::NoOfExistingDevices() on the Device class. If you want to resources use a pointer like this:
public static int* Initialise::NoOfExistingDevices() {
return &no_of_existing_devices;
}
By the way, I advise you to turn the variable private.
I've been making a game which uses the Box2D physics engine, and I've come across some weirdness with the stack pointer (ESP) and multiple inheritance. I've managed to reproduce it in a minimal amount of code, and it seems that the order in which I declare the classes to be used in multiple inheritance seems to dictate whether the program crashes or not.
#include <iostream>
#include <string.h>
using namespace std;
class IPhysicsObject
{
public:
virtual void Collide(IPhysicsObject *other, float angle, int pos)=0;
};
class IBoardFeature
{
public:
IBoardFeature(){};
~IBoardFeature(){};
virtual bool OnAttach(int x){ return true; }
virtual bool Update(int x, float dt)=0;
};
/*
class CScorezone : public IBoardFeature, public IPhysicsObject // this breaks !!!
class CScorezone : public IPhysicsObject, public IBoardFeature // this works !!!
*/
class CScorezone : public IBoardFeature, public IPhysicsObject
{
public:
CScorezone(){}
~CScorezone(void){}
virtual bool Update(int x, float dt)
{
return true;
}
virtual void Collide(IPhysicsObject *other, float angle, int pos)
{
}
virtual bool OnAttach(int x){ return true; }
};
int main(int argc, char *argv[])
{
CScorezone *scoreZone = new CScorezone();
CScorezone *otherZone = new CScorezone();
void *voidZone = scoreZone;
IPhysicsObject *physZone = static_cast<IPhysicsObject*>(voidZone);
physZone->Collide(otherZone, 10, 1);
delete scoreZone;
delete otherZone;
// wait for user input
int x;
cin >> x;
return 0;
}
Running this in debug mode causes the following error
Run-Time Check Failure #0 - The value
of ESP was not properly saved across a
function call. This is usually a
result of calling a function declared
with one calling convention with a
function pointer declared with a
different calling convention.
When I step in to the following line of code:
physZone->Collide(otherZone, 10, 1);
I notice it's going into CScoreZone::OnAttach, not CScoreZone::Collide. Why is this? WHen I change the order of inheritance for CScoreZone, it works fine
class CScorezone : public IPhysicsObject, public IBoardFeature
I'm running on VS2005 SP2 (8.0.50727.768) on Windows XP. Any ideas?
You don't have to assign CScorezone* to void* and then cast it to IPhysicsObject*. Since CScorezone is-a IPhysicsObject you can simply assign to base pointer:
IPhysicsObject *scoreZone = new CScorezone();
IPhysicsObject *otherZone = new CScorezone();
You're also missing public virtual destructor in IPhysicsObject declaration.
Edit:
I a callback situation as you describe in the comments (going through some C api?) I'd use simple struct with a pointer to polymorphic type to avoid undefined casts, something like:
// one more level of indirection
struct cb_data
{
IPhysicsObject* target;
};
// callback function
int callback( void* data )
{
const cb_data& cbd( *static_cast<cb_data*>( data ));
return cbd.target->Collide( ... );
}
The problem is that you cast the pointer to void* first.
The compiler doesn't know then how to perform static cast for the pointer.
It needs to change the pointer value during the cast if you use multiple inheritance to use second superclass virtual table.
Just cast the pointer back to CScoreZone* before using static_cast.
Well, in your code you seem to be deliberately destroying the integrity of a hierarchical cast by using void * as an intermediate type in the cast. ScoreZone * is cast to void * first and then cast to IPhysicsObject *. What you get as the result is undefined behavior.
Why are you doing this? And what did you expect will happen?
Nikolai told you how to avoid casting in the first place with your example given. However if you do need to do a typecast, when working with objects always use dynamic_cast, which does runtime type checking.