I have a problem I am working on. I have a number classes which inherit each other in this pattern:
#include <stdio.h>
#include <stdlib.h>
#include <list>
class TimeObject
{
public:
virtual void Tick()=0;
std::list<TimeObject*> ticks;
};
class MapObject : public TimeObject
{
public:
MapObject()
{
ticks.push_front(this);
printf("Create MapObject %p\n", this);
}
void Tick() { printf("mapobject tick\n"); }
};
class ControlObject : public MapObject
{
public:
ControlObject()
{
ticks.push_front(this);
printf("Create ControlObject %p\n", this);
}
void Tick() { printf("controlobject tick\n"); }
};
int main()
{
ControlObject test;
std::list<TimeObject*>::iterator it = test.ticks.begin();
for(; it != test.ticks.end(); it++)
{
TimeObject *trigger = *it;
trigger->Tick();
}
return 0;
}
The list in the example stores any TimeObject derived class. My problem is that when storing MapObject pointers in the list that are also ControlObjects dispatch always picks the ControlObject function.
Is it possible to trigger the MapObject function with a ControlObject pointer using polymorphism? If it isn't possible/pratical, what would be a good alternative?
You should always store pointer to the Base class A* in the list(std::list< A*>).
The pointer should be correctly made to point either a object of type Bor C before you add the pointer to the container.
Once you do that, dynamic dispatch will take care of calling the correct function for you depending on the actual object type. You don't need to do anything.
I don't know why you want to have any design which is otherwise, If you have any good reasons to do so please let know of them.
Why it always calls ControlObject::tick() in your code?
When you call:
ticks.push_front(this);
in ControlObject::ControlObject() you basically end up overwriting the first pointer you added to the list, The type of the first pushed pointer is not MapObject * anymore it is ControlObject * because you changed the pointer behind its back.You did not transfer ownership of the pointer to the list but you both had shared ownership and you modified the object in your list through the constructor call in derived class. This leaves you with two ControlObject * objects in the list which dynamic dispatch correctly determines and calls the correct method.
There is nothing wrong in what dynamic dispatch does, it is the correct behavior.
If you want to call MapObject::Tick(); then you will explicitly have to tell the compiler to do so, dynamic dispatch works on the actual type of object and it is working correctly.
void controlobject::Tick()
{
printf("controlobject tick\n");
MapObject::Tick();
}
Replicating from the comments:
I am afraid this is a bad design.The code works as it should,it works as defined by the C++ standard.The problem lies in the design.And unless you provide the details of what you are trying to achieve in a broader sense it is difficult and rather pointless to speculate on a new design.
Using a cast on the variable of type C to the type B should do the trick.
C c;
B b;
c.Function();
((B)c).Function();
A * l[] = {&c,&b,&c};
l[0]->Function();
l[1]->Function();
l[2]->Function();
B test = *(B*)l[0];
test.Function();
In your current example you should be able to call both virtual members (or just the one depending on the underlying type) by calling MapObject::Tick() inside ControlObject::Tick():
class ControlObject : public MapObject
{
public:
ControlObject()
{
ticks.push_front(this);
printf("Create ControlObject %p\n", this);
}
void Tick() { printf("controlobject tick\n"); MapObject::Tick(); }
};
The explicit function call notation is required.
Related
I'm trying to overload the -> operator to eventually execute something along the lines:
MyInterface *myInstance = (MyInterface *)(new A());
myInstance->Toggle(); //this works wonderfully
std::shared_ptr<Wrapper<MyInterface>> sharedPtrWrapper = std::make_shared<Wrapper<MyInterface>>(myInstance);
//the next line doesn't compile, I would like to achieve something like this, but even
//sharedPtrWrapper.get()->Toggle();
//would be nice to achieve, is this possible?
sharedPtrWrapper->Toggle();
//this works:
sharedPtrWrapper->operator->()->Toggle();
Note: I have no control over MyInterface, cannot implement the pure virtual destructor.
Here is what I tried (the below code runs):
#import <memory>
#import <iostream>
struct MyInterface {
virtual bool Toggle() = 0;
};
class A : public MyInterface {
public:
bool Toggle() {
stateEnabled = !stateEnabled;
std::cout<<"current state " << stateEnabled << std::endl;
return true;
}
private:
bool stateEnabled = false;
};
template <typename T>
class Wrapper {
private:
T *unsafePointer = nullptr;
public:
Wrapper<T>()
{ }
T *operator->() const {
return unsafePointer;
}
T *getInner() {
return unsafePointer;
}
Wrapper<T>(T *stuff) {
unsafePointer = stuff;
}
~Wrapper<T>() {}
};
int main(int argc, const char * argv[]) {
MyInterface *myInstance = (MyInterface *)(new A());
myInstance->Toggle();
Wrapper<MyInterface> wrapperS(myInstance);
wrapperS->Toggle();
std::shared_ptr<Wrapper<MyInterface>> sharedPtrWrapper = std::make_shared<Wrapper<MyInterface>>(myInstance);
sharedPtrWrapper->operator->()->Toggle();
sharedPtrWrapper.operator->()->operator->()->Toggle();
sharedPtrWrapper.get()->operator->()->Toggle();
(*sharedPtrWrapper).operator->()->Toggle();
return 0;
}
Output:
current state 1
current state 0
current state 1
current state 0
current state 1
current state 0
Program ended with exit code: 0
To reiterate:
This code doesn't compile:
sharedPtrWrapper->Toggle();
How to make it compile?
Edit : I'm using a wrapper because I have no control over the MyInterface, I get it from a library, also shared_ptr<MyInterface> mySharedPointer = std::make_shared<MyInterface>(myInstance); doesn't compile, because of the missing pure virtual destructor from the above mentioned interface.
Edit2: Example library usage in pseudocode:
void firstcallbackFromLib(Framework *framework) {
MyInterface *myInstance = framework->getInstance();
{
Wrapper<MyInterface> wrapperS(myInstance);
std::shared_ptr<Wrapper<MyInterface>> sharedPtrWrapper = std::make_shared<Wrapper<MyInterface>>(wrapperS);
//assign sharedPtrWrapper and framework to static instances
}
}
void myFunction() {
sharedPtrWrapper->Toggle(); //this doesn't work, this is what i'm trying to achieve
sharedPtrWrapper->operator->()->Toggle(); //this ugly thing works
}
void lastUninitCallbackFromLibrary() {
MyInterface *p = sharedPtrWrapper.get()->getInner();
framework->releaseInterface(p);
//etc
}
The problem is, that shared_ptr behaves like a pointer and Wrapper does that as well. In summary, you have code that behaves like a pointer to a pointer. In short, you could call (*sharedPtrWrapper)->Toggle(); instead of the abomination sharedPtrWrapper->operator->()->Toggle();.
Careful though: It's unclear what all this is supposed to achieve, because the example code is just an abstraction of your actual code. So, maybe it would just be more elegant to put a forwarding Toggle() method into class Wrapper, but that's impossible to tell with the info provided here.
I am confused about the question. Why wrapper class that does nothing?
If you want to put a class inside shared pointer yet do something uncommon at destruction: like, calling dll's function that performs the destruction, do some preprocessing, perform file closure instead of delete, or do nothing at all if that's what you want. Then you can simply specify it at shared pointer instantiation:
https://en.cppreference.com/w/cpp/memory/shared_ptr/shared_ptr - see construction option 5.
You don't need your wrapper at all.
shared_ptr<MyInterface> mySharedPointer = std::make_shared<MyInterface>();
wont work because MyInterface is an abstract class. But, just like you can do
MyInterface *myInstance = new A();
To have a MyInterface * that points to a concrete derived object, you can use
std::shared_ptr<MyInterface> sharedPtr = std::make_shared<A>();
To get a std::shared_ptr<MyInterface> that points to a concrete derived object. You can then use sharedPtr to access Toggle like
sharedPtr->Toggle();
You can see that working in this live example
sharedPtrWrapper->Toggle(); doesn't compile because of operator-> chaining rules explained well in this answer. In principle: if your object is NOT a pointer, operator-> is called recursively, if it is a pointer, member access is performed. Now std::shared_ptr has overloaded operator-> to access the raw Wrapper<MyInterface>* pointer kept inside and when it is applied on it, it tries to access Toggle, which does not exist.
For clarity note that this code also will not compile:
Wrapper<MyInterface>* wrapper = new Wrapper<MyInterface>(myInstance);
wrapper->Toggle();
You can do this however:
(*sharedPtrWrapper)->Toggle();
Use:
struct CleanupMyInterface {
SomeTypeFromLib* somePointerFromLib = nullptr;
void operator()( MyInterface* ptr ) const {
if (somePointerFromLib && ptr)
somePointerFromLib->releaseInterface(ptr);
}
};
std::shared_ptr<MyInterface> sharedPtr( CreateAnInstanceOfAFromLibrary(), CleanupMyInterface{somePointerFromLib} );
shared_ptr has type-erased destruction, there is no need for a virtual destructor.
I have 1 question because I am pretty curious how to handle with such problem.
I have base class called "Pracownik" (Worker) and 2 subclasses which are made from public Pracownik;
- Informatyk (Informatic)
- Księgowy (Accountant)
Writing classes is easy. Made them pretty fast but I have small problem with main because I am helping friend with program but I was not using C++ for a while. So:
This is my header file "funkcje.h"
#include <iostream>
using namespace std;
class Pracownik
{
private:
string nazwisko;
int pensja;
public:
Pracownik(string="",int=0);
~Pracownik();
string getNazwisko();
int getPensja();
friend double srednia_pensja(int,Pracownik);
};
class Informatyk : public Pracownik
{
private:
string certyfikat_Cisco;
string certyfikat_Microsoft;
public:
Informatyk(string="",int=0, string="", string="");
~Informatyk();
void info();
};
class Ksiegowy : public Pracownik
{
private:
bool audytor;
public:
Ksiegowy(string="",int=0, bool=false);
~Ksiegowy();
void info();
};
double srednia_pensja(int,Pracownik);
These are definitions of my functions "funkcje.cpp"
#include "funkcje.h"
Pracownik::Pracownik(string a,int b)
{
nazwisko=a;
pensja=b;
}
Pracownik::~Pracownik()
{
}
string Pracownik::getNazwisko()
{
return nazwisko;
}
int Pracownik::getPensja()
{
return pensja;
}
Informatyk::Informatyk(string a, int b, string c, string d) : Pracownik(a,b)
{
certyfikat_Cisco=c;
certyfikat_Microsoft=d;
}
Informatyk::~Informatyk()
{
}
Ksiegowy::Ksiegowy(string a, int b, bool c) : Pracownik(a,b)
{
audytor=c;
}
Ksiegowy::~Ksiegowy()
{
}
void Informatyk::info()
{
cout<<"Nazwisko pracownika: "<<Pracownik::getNazwisko()<<endl;
cout<<"Pensja pracownika: "<<Pracownik::getPensja()<<endl;
cout<<"Certyfikat Cisco: "<<certyfikat_Cisco<<endl;
cout<<"Certyfikat Microsoft: "<<certyfikat_Microsoft<<endl;
}
void Ksiegowy::info()
{
cout<<"Nazwisko pracownika: "<<Pracownik::getNazwisko()<<endl;
cout<<"Pensja pracownika: "<<Pracownik::getPensja()<<endl;
cout<<"Audytor: ";
if(audytor)
cout<<"Tak"<<endl;
else
cout<<"Nie"<<endl;
}
double srednia_pensja(int a,Pracownik *b)
{
return 0;
}
And finally main!
#include <iostream>
#include "funkcje.h"
using namespace std;
int main()
{
Pracownik lista[10];
Pracownik *lista_wsk = new Pracownik[10];
Informatyk a("Kowalski1",1000,"Cisco1","Microsoft1");
Informatyk b("Kowalski2",2000,"Cisco2","Microsoft2");
Informatyk c("Kowalski3",3000,"Cisco3","Microsoft3");
Ksiegowy d("Kowalski4",4000,1);
Ksiegowy e("Kowalski5",5000,0);
lista[0]=a;
lista[1]=b;
lista[2]=c;
lista[3]=d;
lista[4]=e;
Informatyk *ab = new Informatyk("Kowalski1",1000,"Cisco1","Microsoft1");
Informatyk *ac = new Informatyk("Kowalski2",2000,"Cisco2","Microsoft2");
Informatyk *ad = new Informatyk("Kowalski3",3000,"Cisco3","Microsoft3");
Ksiegowy *ae = new Ksiegowy("Kowalski4",3000,1);
Ksiegowy *af = new Ksiegowy("Kowalski5",3000,0);
lista_wsk[0]=*ab;
lista_wsk[1]=*ac;
lista_wsk[2]=*ad;
lista_wsk[3]=*ae;
lista_wsk[4]=*af;
for(int i;i<5;i++)
{
lista[i].info();
cout<<endl;
}
cout<<endl;
// for(int i;i<5;i++)
// {
// lista_wsk[i].info();
// }
return 0;
}
Ok and here goes my questions:
I had to create array which is filled with base class objects "Pracownik".
Secondary i had to create array which is full of pointers to class "Pracownik" objects.
(Hope those 2 first steps are done correctly)
Next thing I had to write to array 3 objects of class Informatic and 2 of class Accountant.
So I ve created 5 objects manually and added them into the array in such way array[0]=a;. I guess this is still good.
Next thing i had to create and add similar objects to array of pointers using new. So I ve created array with new and pointers to objects with new. (Hope thats correct 2).
And FINALLY:
I had to use info() on added to array objects.
This is my main question if my array is type "Pracownik" and I want to use function info() from subclasses how should I do that? And how compiler will know if he should use info() from Accountant or Informatic while I am trying to show those information using "for".
In an array of Pracownik, the elements are of type Pracownik. Any information about the objects being of a subclass of Pracownik are lost when you copy the elements into the array.
This is called object slicing and leads to the fact that there is no way to invoke Informatyk::info() on these objects.
If you want to call methods of a subclass, you have to prevent object slicing by storing pointers or references in the array.
As Oswald says in his answer,
Pracownik * lista_wsk = new Pracownik[10];
allocates an array of 10 Pracownik objects. This is probably not what you want. With polymorphism involved, we usually want to deal with pointers or references. Hence, you'd want an array of Pracownik * pointers. Since you already know at compile-time that it will have 10 members, there is no need for a dynamic allocation here. I think you've meant to write
Pracownik * lista_wsk[10];
instead. Now we don't put objects but pointers to objects into the array. For example:
lista_wsk[2] = new Informatyk("Kowalski3", 3000, "Cisco3", "Microsoft3");
And then we can iterate over the items like so:
for (unsigned i = 0; i < 10; ++i)
std::cout << lista_wsk[i]->getNazwisko() << std::endl;
As you have already discovered, it is impossible to call a subclass function member on a superclass object. It would be possible to figure out the actual type at run-time yourslf by means of a cast.
for (unsigned i = 0; i < 10; ++i)
if (Informatyk * info_ptr = dynamic_cast<Informatyk *>(lista_wsk[i]))
info_ptr->info();
dynamic_cast returns a pointer to the target class if this is possible or a nullptr (which evaluates to false, hence the conditional) otherwise. Note however that this is considered very poor style. It is better to use virtual functions. Therefore, add
virtual void
info()
{
// Do what is appropriate to do for a plain Pracownik.
// Maybe leave this function empty.
}
to the superclass and again to the subclass
virtual void
info() // override
{
// Do what is appropriate to do for an Informatyk.
}
The function in the subclass with the same signature is said to override the function inherited from the superclass. Since the function is marked as virtual, the compiler will generate additional code to figure out at run-time what version of the function to call.
If you are coding C++11, you can make the override explicit by placing the keyword override after its type as shown above (uncomment the override). I recommend you use this to avoid bugs that arise from accidental misspelling or other typos.
In my class implementation, I have something like this:
base class
class swcWidget :
public swcRectangle
{
public:
swcWidget();
virtual ~swcWidget();
void update(float dt);
protected:
inline virtual void oPaintOnTop() { }
private:
};
derived class
class swcButton :
public swcWidget
,public swcText
{
public:
swcButton();
virtual ~swcButton();
static const int DEFAULT_SIZE = 20;
protected:
private:
void oPaintOnTop();
};
class swcApplication
{
public:
swcApplication(int argc, char *argv[]);
virtual ~swcApplication();
int run();
struct Controls
{
typedef std::vector<swcWidget*> vWidgets; //option 1
~Controls();
/////////////////////////////////
// M A I N P R O B L E M //
/////////////////////////////////
void add(swcWidget &&widgets); //most preferred option
//but gets demoted to base class.
void add(swcWidget *widgets); //second choice
//but should I make a copy of it?
//or just make a reference to it?
//and this one does what I wanted to.
//but still unsure on other things I don't know
void add(swcWidget *&&widgets); //this compiles fine (?)
//I don't know what kind of disaster I can make into this, but still does not do what I wanted.
inline vWidgets &getWidgets() {
return widgets;
}
private:
vWidgets widgets;
};
Controls controls;
};
I know some working option like this:
making the
swcApplication::Controls::widgets
as type of
std::vector<std::shared_ptr<swcWidget>>
but my code will bind into std::shared_ptr and I cannot make simple syntax like this:
swcButton btn;
app.controls.add(std::move(btn));
Example usage:
main.cpp
int main(int argc, char *argv[])
{
swcApplication app(argc, argv);
app.windows.create(640, 480);
if (font->load("fonts\\georgia.fnt") != BMfont_Status::BMF_NO_ERROR)
{
puts("failed to load \"georgia.fnt\"");
}
{
swcButton btn;
btn.setPosition(100, 100);
btn.setFont(font);
btn.text = "Ey!";
app.controls.add(std::move(&btn));
// btn.text = "Oy!";
}
return app.run();
}
Update:
Here's the temporary definition of swcApplication::Controls::add() although it may still vary
void swcApplication::Controls::add(swcWidget &&widget)
{
widgets.push_back(std::move(widget));
}
If a class is moveable, then it will in turn move it's members one by one. For this to be efficient, these members must either be small POD's or must be allocated on the heap. You must add this functionality, not forget to move any member, and object slicing is a concern to watch out for.
Given the class is non-trivial, you have the most efficient move construct available when you just use a pointer directly (at the cost of heap allocation time of course). No slicing is possible, and no member can be forgotten to be moved, since you move the whole object in one go. The one hurdle to watch out for is to keep track of who owns the pointers - you'd better set it in stone, but if that's done then there are no issues anymore.
The move semantics are wonderful, but if your classes are somewhat involved I think pointers in this case are easier / more efficient to work with. I'd thus stick with the pointer variant, and make sure your collection will own the pointers (and release them again via RAII) - make liberal use of comment in your public interface saying so. You can do this by storing some form of smart pointer (hint: be careful with unique_ptr's!), or (less safe) make and always use a Clear() member that delete's all pointers before clear()'ing the collection.
EDIT
Whet you define your widgets member to be of type vector, then example code could be:
To class swcApplication add:
void swcApplication::Controls::ClearWidgets() {
for (auto& nextWidget: widgets) {
delete nextWidget;
}
widgets.clear();
}
Don't forget to call ClearWidgets at the appropriate times (like in your destructor).
Adding widgets can be done with:
// Note: any passed widget will not be owned by you anymore!
template <typename Widget>
void swcApplication::Controls::add(Widget*& widget) {
widgets.push_back(widget);
widget = nullptr;
}
From now on you can add widgets like
swcButton* btn = new swcButton;
app.controls.add(btn);
// btn is now owned by app.controls, and should be set
// to nullptr for you to prevent misuse like deleting it
Using a smart pointer here should make it more safe, though storing unique_ptr's makes accessing them a bit error-prone (watch out for grabbing ownership back from the container when accessing them), and a shared_ptr gives overhead which might be unneeded here.
#define classAnum 2;
#define classBnum 3;
class Base
{
virtual int open()=0;
virtual int close()=0;
}
class A:public Base
{
virtual int open();
virtual int close();
};
class B:public Base
{
virtual int open();
virtual int close();
}
int main()
{
A classA[classAnum];
B classB[classBnum];
openAnyClass(1);
CloseAnyClass(2);
}
I want to achieve functionality like this.
openAnyClass(1);
CloseAnyClass(2);
these 2 functions should be able to call open() and close() from any of class A and B.
openAnyClass(1) would call the open() function of 1st object in the array of either classA or classB.
open() --> will have different implementation in class A and class B. and open() in classA may be called from multiple clients and max. no. of clients is # defined.
At a time only one open() from any of the classA or classB is called. I dont want to have several copies of the same code.
with just one function i want call open() of any of class A and any of client.
for Eg: in the below statement i want to call open() of class A of client1. the param to openAnyClass(int) indicates the client Id. This could also meant classB[1].open();
'openAnyClass(1) = classA[1].open();'
What is the best way of doing this?
This is the reason for having a command base class that you derive from; that way you can have a pointer or reference to a class and call the open/close method in the derived classes via the virtual functions.
So if you had
Base *generic_class_pointer = new class A();
generic_class_pointer->open();
The generic_class_pointer->open() would invoke the code defined in class A.
What you're trying to do with two arrays that store objects, one for classes A and one for classes B is not required, you can have a single array that refers to classes of type Base and access via this.
The original code is not really a good way of working, it's better to do this via a list (eg. stl::vector).
Base* class_storage[StorageSize];
int openAnyClass(int id)
{
if (id < 0 || id >= StorageSize || class_storage[id] == 0)
return 0; // or other error indication
else
return class_storage[id]->open();
}
int CloseAnyClass(int id)
{
if (id < 0 || id >= StorageSize || class_storage[id] == 0)
return 0; // or other error indication
else
return class_storage[id]->close();
}
int main()
{
memset(class_storage,0,sizeof(class_storage));
class_storage[1] = new A();
class_storage[2] = new B();
openAnyClass(1);
CloseAnyClass(2);
}
The above code isn't a complete solution, for example the original doesn't have virtual destructors which is a good practice to always use - in case a derived class needs to do cleanup.
Also the deletion of the objects allocated into the class_storage isn't freed on my sample. It doesn't matter at global level because they will be freed upon exit, however most of the time you need to manage everything acquired via new() otherwise you'll get memory leaks.
so classA is an array of A, and same for classB. and calling openAnyClass(1), means call open() on all instances of A, and closeAnyClass() means call close() on all instances of classB. well if this is the case, the question is really complicated formulated
anyways there's no no known out of the box method to do that. you have to iterate on all elements of the array and call open() or close(). alternatively you can use boost foreach
http://www.boost.org/doc/libs/1_39_0/doc/html/foreach.html
or implement your own foreach method
If I understand your question correctly, you want to call different implementations of a pure virtual function. Assuming you have provided implementations of class A and class B, you should be able to make use of polymorphism and call open()/close() from a pointer/reference to a Base instead of A or B.
Instead of creating two arrays for A and B, you can create only one array of Base pointers.
Example:
Base* base[basenum];
void openAnyClass( const int i )
{
if( i < basenum && i >=0 && base[i] != NULL )
base[i]->open();
}
int main(void)
{
base[0] = new A();
base[1] = new B();
...
openAnyClass(1);
closeAnyClass(2);
for( int i = 0 ; i < basenum ; i++ )
delete base[i];
}
As a side note, I think it would be better to make use of open and close functions like these:
void openAnyClass( Base& base );
void closeAnyClass( Base& base );
Rather than using a global variable to store the objects and passing an index, pass the pointer/reference of the object to the function and the function would call the appropriate method(whether the method of A or B).
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.