When is (this != this) in C++? - c++

I have a very strange question.
I have a class/function :
class MCBSystem {
[...]
template <class Receiver>
void setCallBack(int i, Receiver* receiver, void(Receiver::*function)(void*)) {
iCallBacks.at(i) = new CallBack<Receiver>(receiver, function, this);
};
};
And I inherit it (multiply) in another class :
class MenuBox : public OverlayBox, public HIDListener, public FANLib::MCBSystem {
[...]
};
Now, if I call the "setCallBack" function :
menuBox->setCallBack(MenuBox::CLICKED, this, &SubMain::widgetClicked);
then "menuBox" has a value say 0x06cf22b8 but inside "setCallBack", "this" is 0x06cf2370.
Can someone explain what on earth is going on?
[EDIT:] The true question is : if I need to store 'this' inside 'setCallBack', how can I check later that 'menuBox == this'?
Many thanks in advace!

Yes, the this pointer has to be patched to allow for multiple inheritance polymorphism. As a zeroth-order approximation, an instance of a class C that inherits from A and B can be thought to include an instance of A followed by an instance of B. Now if you have a pointer to a C instance and convert that to an instance of B, the this pointer must be different because the B instance is located after the C instance in memory. See this paper for an in-depth discussion.
Little test program:
#include <iostream>
struct A { int i; };
struct B { int j; };
struct C: A, B { };
#define PRINT(expr) std::cout << #expr " = " << expr << std::endl
int main() {
C* c = new C;
B* b = c;
PRINT(b);
PRINT(c);
PRINT(static_cast<B*>(c));
}

Given any pointer to an object, it's value will be different based on whatever it is cast to.
Within a member function of MenuBox, this points to the MenuBox part of the object in question.
However, in setCallBack, it is being cast to a pointer to the Receiver part of the object.
To put it another way, this will always equal this, but for any pointer p static_cast<MenuBox>(p) will never equal static_cast<Receiver>(p).

Related

How to resolve memory related errors that arise from interaction between C objects in a C++ wrapper?

The problem
I am writing a thin C++ wrapper around an object oriented C library. The idea was to automate memory management, but so far its not been very automatic. Basically when I use my wrapper classes, I get all kinds of memory access and inappropriate freeing problems.
Minimal example of C library
Lets say the C library consists of A and B classes, each of which have a few 'methods' associated with them:
#include <memory>
#include "cstring"
#include "iostream"
extern "C" {
typedef struct {
unsigned char *string;
} A;
A *c_newA(const char *string) {
A *a = (A *) malloc(sizeof(A)); // yes I know, don't use malloc in C++. This is a demo to simulate the C library that uses it.
auto *s = (char *) malloc(strlen(string) + 1);
strcpy(s, string);
a->string = (unsigned char *) s;
return a;
}
void c_freeA(A *a) {
free(a->string);
free(a);
}
void c_printA(A *a) {
std::cout << a->string << std::endl;
}
typedef struct {
A *firstA;
A *secondA;
} B;
B *c_newB(const char *first, const char *second) {
B *b = (B *) malloc(sizeof(B));
b->firstA = c_newA(first);
b->secondA = c_newA(second);
return b;
}
void c_freeB(B *b) {
c_freeA(b->firstA);
c_freeA(b->secondA);
free(b);
}
void c_printB(B *b) {
std::cout << b->firstA->string << ", " << b->secondA->string << std::endl;
}
A *c_getFirstA(B *b) {
return b->firstA;
}
A *c_getSecondA(B *b) {
return b->secondA;
}
}
Test the 'C lib'
void testA() {
A *a = c_newA("An A");
c_printA(a);
c_freeA(a);
// outputs: "An A"
// valgrind is happy =]
}
void testB() {
B *b = c_newB("first A", "second A");
c_printB(b);
c_freeB(b);
// outputs: "first A, second A"
// valgrind is happy =]
}
Wrapper classes for A and B
class AWrapper {
struct deleter {
void operator()(A *a) {
c_freeA(a);
}
};
std::unique_ptr<A, deleter> aptr_;
public:
explicit AWrapper(A *a)
: aptr_(a) {
}
static AWrapper fromString(const std::string &string) { // preferred way of instantiating
A *a = c_newA(string.c_str());
return AWrapper(a);
}
void printA() {
c_printA(aptr_.get());
}
};
class BWrapper {
struct deleter {
void operator()(B *b) {
c_freeB(b);
}
};
std::unique_ptr<B, deleter> bptr_;
public:
explicit BWrapper(B *b)
: bptr_(std::unique_ptr<B, deleter>(b)) {
}
static BWrapper fromString(const std::string &first, const std::string &second) {
B *b = c_newB(first.c_str(), second.c_str());
return BWrapper(b);
}
void printB() {
c_printB(bptr_.get());
}
AWrapper getFirstA(){
return AWrapper(c_getFirstA(bptr_.get()));
}
AWrapper getSecondA(){
return AWrapper(c_getSecondA(bptr_.get()));
}
};
Wrapper tests
void testAWrapper() {
AWrapper a = AWrapper::fromString("An A");
a.printA();
// outputs "An A"
// valgrind is happy =]
}
void testBWrapper() {
BWrapper b = BWrapper::fromString("first A", "second A");
b.printB();
// outputs "first A"
// valgrind is happy =]
}
Demonstration of the problem
Great, so I move on and develop the full wrapper (lot of classes) and realise that when classes like this (i.e. aggregation relationship) are both in scope, C++ will automatically call the descructors of both classes separately, but because of the structure of the underlying library (i.e. the calls to free), we get memory problems:
void testUsingAWrapperAndBWrapperTogether() {
BWrapper b = BWrapper::fromString("first A", "second A");
AWrapper a1 = b.getFirstA();
// valgrind no happy =[
}
Valgrind output
Things I've tried
Cloning not possible
The first thing I tried was to take a copy of A, rather than having them try to free the same A. This, while a good idea, is not possible in my case because of the nature of the library I'm using. There is actually a catching mechanism in place so that when you create a new A with a string its seen before, it'll give you back the same A. See this question for my attempts at cloning A.
Custom destructors
I took the code for the C library destructors (freeA and freeB here) and copied them into my source code. Then I tried to modify them such that A does not get freed by B. This has partially worked. Some instances of memory problems have been resolved, but because this idea does not tackle the problem at hand (just kind of temporarily glosses over the main issue), new problems keep popping up, some of which are obscure and difficult to debug.
The question
So at last we arive at the question: How can I modify this C++ wrapper to resolve the memory problems that arise due to the interactions between the underlying C objects? Can I make better use of smart pointers? Should I abandon the C wrapper completly and just use the libraries pointers as is? Or is there a better way I haven't thought of?
Thanks in advance.
Edits: response to the comments
Since asking the previous question (linked above) I have restructed my code so that the wrapper is being developed and built in the same library as the one it wraps. So the objects are no longer opaque.
The pointers are generated from function calls to the library, which uses calloc or malloc to allocate.
In the real code A is raptor_uri* (typdef librdf_uri*) from raptor2 and is allocated with librdf_new_uri while B is raptor_term* (aka librdf_node*) and allocated with librdf_new_node_* functions. The librdf_node has a librdf_uri field.
Edit 2
I can also point to the line of code where the same A is returned if its the same string. See line 137 here
The problem is that getFirstA and getSecondA return instances of AWrapper, which is an owning type. This means that when constructing an AWrapper you're giving up the ownership of an A *, but getFirstA and getFirstB don't do that. The pointers from which the returned objects are constructed are managed by a BWrapper.
The easiest solution is that you should return an A * instead of the wrapper class. This way you're not passing the ownership of the inner A member. I also would recommend making the constructors taking pointers in the wrapper classes private, and having a fromPointer static method similar to fromString, which takes ownership of the pointer passed to it. This way you won't accidently make instances of the wrapper classes from raw pointers.
If you want to avoid using raw pointers or want to have methods on the returned objects from getFirstA and getSecondA you could write a simple reference wrapper, which has a raw pointer as a member.
class AReference
{
private:
A *a_ref_;
public:
explicit AReference(A *a_ref) : a_ref_(a_ref) {}
// other methods here, such as print or get
};
You are freeing A twice
BWrapper b = BWrapper::fromString("first A", "second A");
When b goes out of scope, c_freeB is called which also calls c_freeA
AWrapper a1 = b.getFirstA();
Wraps A with another unique_ptr, then when a1 goes out of scope it will call c_freeA on the same A.
Note that getFirstA in BWrapper gives ownership of an A to another unique_ptr when using the AWrapper constructor.
Ways to fix this:
Don't let B manage A memory, but since you are using a lib that won't be possible.
Let BWrapper manage A, don't let AWrapper manage A and make sure the BWrapper exists when using AWrapper. That is, use a raw pointer in AWrapper instead of a smart pointer.
Make a copy of A in the AWrapper(A *) constructor, for this you might want to use a function from the library.
Edit:
shared_ptr won't work in this case because c_freeB will call c_freeA anyways.
Edit 2:
In this specific case considering the raptor lib you mentioned, you could try the following:
explicit AWrapper(A *a)
: aptr_(raptor_uri_copy(a)) {
}
assuming that A is a raptor_uri. raptor_uri_copy(raptor_uri *) will increase the reference count and return the same passed pointer. Then, even if raptor_free_uri is called twice on the same raptor_uri * it will call free only when the counter becomes zero.

Auto return type of a function in c++

I have a problem that Im not able to solve. I have tried to find similar question here, but didnt find working solution for me.
My structure is:
class Base
{
unsigned int ID;
};
class Position: public Base
{
float x,y;
Position(float a, float b): x(a), y(b) {}
}
class Mass: public Base
{
float mass;
Mass(float a): mass(a) {}
}
I store pointers to all attributes in a map accesed with strings.
I would like to have a function, that can return any attribute from this list using names.
Structure and desired functionality should be like this:
std::map<string, Base*> attributes;
???? getAtt(string name)
{
return attributes[name];
}
Position pos(1,2);
Mass mass(25.6);
attributes.emplace("TEST_POSITION", &pos);
attributes.emplace("TEST_MASS") &mass);
cout << "Mass of this object is " <<getAtt("TEST_MASS").mass << endl;
cout << "X - Position of this object is " << getAtt("TEST_POSITION").x ;
PRINTS: Mass of this object is 25.6
X - Position of this object is 1
This function, addition of attributes and memory managment should be encapsuled in another class, but I think that wont be such problem after i get this thing solved.
So is there a way to do that? I was thinking about templates, but I dont understand them enough to make them work :( I was thinking about not storing all attributes in one array, but this way it is really easy.
Thanks for any suggestions :)
Your getAtt will return a Base*, like this:
Base* getAtt(const string& name)
{
...
}
But Base class doesn't provide a interface for all its derived class, so you can't just do
getAtt("TEST_MASS").mass
instead you have to do this:
dynamic_cast<Mass*>(getAtt("TEST_MASS"))->mass;
dynamic_cast<Position*>(getAtt("TEST_POSITION"))->x;
There are alternatives, for example you can use a tagged union, but that might be too complex for your problem.
By the way, [] operator of map will create a element if it doesn't exist, so you need to check getAtt isn't returning a nullptr.
The compiler cannot deduce the return type without you hinting it. You can use a template for that:
template <typename T>
T& getAtt(string name)
{
return dynamic_cast<T&>(*attributes.at(name));
}
Edit: use at instead of [], [] has the side-effect that it creates non-existing keys.
And then call it like this:
getAtt<Mass>("TEST_MASS").mass
getAtt<Position>("TEST_POSITION").x
However, this code would be nightmare to debug. Try to avoid generic attributes and use strong-typed variables, ie. instead of:
std::map<string, Base*> attributes;
attributes.emplace("mass", Mass(…));
attributes.emplace("position", Position(…));
use:
Mass mass;
Position position;
You can return a reference object that has a conversion operator to the type. If the conversion is implemented with a dynamic cast, the result will be NULL if an attempt is made to assign the object to something that it is not. Dynamic cast requires Base to have a virtual method (you could just add a virtual destructor).
class Base {
unsigned int ID;
protected:
virtual ~Base () {}
};
class Ref {
friend Ref getAtt (std::string name);
Base *ref_;
Ref (Base *p = 0) : ref_(p) {}
public:
template <typename D> operator D * () const {
return dynamic_cast<D *>(ref_);
}
};
Ref getAtt (std::string name) { return attributes[name]; }
This technique does not allow you to treat a Ref as any particular type. It allows you to assign it to something that it is allowed to become.
Mass *m = getAtt("TEST_MASS");
Position *p = getAtt("TEST_POSITION");
cout << "Mass of this object is " << m->mass << endl;
cout << "X - Position of this object is " << p->x ;
If the resulting pointer is NULL, it means either the item did not exist, or you are attempting to assign it to the wrong thing.
Position *p = getAtt("TEST_MASS");
assert(p == NULL);

why do we need to cast from base type to derived type and back?

I know about the existence of static_cast, dynamic_cast. But I can't seem to find out a concrete reason to convince myself about why cast from base to derive or vice versa?
Any example in code would be appreciated.
UPDATE
class Base
{
public:
void foo();
private:
int _x;
};
class Derive: Base
{
};
Base *b = new Derive; //will b behave the same as if it's a Derive *?
Derive *d = new Base; //I think d can't behave like a Derive * but Base *, right?
Actually, those casts are obvious marks of something unsual going on in the code, so in a perfect world, you shouldn't use them.
But in some cases they are the right tool for the job.
For static_cast, there are basically 2 cases:
1. Primitive conversion.
When you really need some integer number to be processed in a calculus involving floats.
float ratio = static_cast<float>( pixel_pos.x ) / static_cast<float>( pixel_pos.y ); // x and y are integers because pixel positions are absolute, but we need to get a floating point value here
2. You got an object from some external API and you want to get the specific child-type.
Thing* thing = factory.create( "shoe" ); // Even if I don't have it's real type, I know it's a shoe!
Shoe* shoe = static_cast<Shoe*>( thing ); // I need to use Shoe interface so lets cast it.
If you designed the system, maybe you could have done it better to avoid the cast. But if you didn't and the API you're using provide the base type as a way for you to work with it, then you don't have any other choice than to cast.
static_cast is useful also because it lets you assume something at compile time, so you should use it first because it requires you to be sure about what you are doing.
3.You don't know what is the real type of the object.
However, there is a specific case when you need to know the real type at runtime because there is no way for you to know it at another time. Typical case is when you're receiving some kind of objects from an external system and there is no other information about the real type of the object
void on_something_happen( const Event& event ) // callback triggered when an event occured in the library system this callback is plugged in
{
// here I want to manage two cases
ThingEvent* thing_event = dynamic_cast<ThingEvent*>( &event );
if( thing_event )
{
// do my thing
}
else
{
// ok this event HAVE TO be a FooEvent, otherwise this should crash
FooEvent& foo_event = dynamic_cast<FooEvent&>( event );
// do my thing
}
}
suppose you have:
struct A {
int i;
};
struct B : A {
char c;
};
struct C : A {
double d;
};
And some function f() returning a pointer to A, for which you don't know the definition.
When you do:
A * a = f();
How do you know what you can do with a? According to the definition above every B and C is also an A, so you know that if a is not null you can use its i data member without problems. On the other hand, in order to use either c or d you need to know the actual type of a, and that is achieved with dynamic_cast.
Let's suppose you know that a is actually a pointer to B. What you can do is:
B * b = dynamic_cast<B *>(a);
if ( b != 0 )
b->c = 'd';
(Yes, I know we assumed you know it, but such assumptions never hold forever...)
The typical situation is the need to add an operation to an existing data type, but you can't add it directly.
Suppose you have this class structure:
struct Base {
virtual doSomething() = 0;
};
struct Derived1 : Base {
virtual doSomething();
int x,y;
};
struct Derived2 : Base {
virtual doSomething();
float a,b;
};
Now you are writing a function that is passed a Base&:
void f(Base& base);
You want to be able to print information about base, but for whatever reason, you aren't allowed to modify Base to add this operation (it is part of a commercial library, for example). In that case you may have to do something like this:
void f(Base& base)
{
if (Derived1* p=dynamic_cast<Derived1*>(&base)) {
cout << "Derived1{" << p->x << "," << p->y << "}\n";
}
else if (Derived2* p=dynamic_cast<Derived2*>(&base)) {
cout << "Derived2{" << p->a << "," << p->b << "}\n";
}
else {
cout << "Unknown type\n";
}
}
This is typically considered bad style in an object-oriented language though. One problem is that if you add a new class to your hierarchy, then the compiler won't help you find the places where you need to add code to handle operations on instances of that new class.

C++ Class design - easily init / build objects

Using C++ I built a Class that has many setter functions, as well as various functions that may be called in a row during runtime.
So I end up with code that looks like:
A* a = new A();
a->setA();
a->setB();
a->setC();
...
a->doA();
a->doB();
Not, that this is bad, but I don't like typing "a->" over and over again.
So I rewrote my class definitions to look like:
class A{
public:
A();
virtual ~A();
A* setA();
A* setB();
A* setC();
A* doA();
A* doB();
// other functions
private:
// vars
};
So then I could init my class like: (method 1)
A* a = new A();
a->setA()->setB()->setC();
...
a->doA()->doB();
(which I prefer as it is easier to write)
To give a more precise implementation of this you can see my SDL Sprite C++ Class I wrote at http://ken-soft.com/?p=234
Everything seems to work just fine. However, I would be interested in any feedback to this approach.
I have noticed One problem. If i init My class like: (method 2)
A a = A();
a.setA()->setB()->setC();
...
a.doA()->doB();
Then I have various memory issues and sometimes things don't work as they should (You can see this by changing how i init all Sprite objects in main.cpp of my Sprite Demo).
Is that normal? Or should the behavior be the same?
Edit the setters are primarily to make my life easier in initialization. My main question is way method 1 and method 2 behave different for me?
Edit: Here's an example getter and setter:
Sprite* Sprite::setSpeed(int i) {
speed = i;
return this;
}
int Sprite::getSpeed() {
return speed;
}
One note unrelated to your question, the statement A a = A(); probably isn't doing what you expect. In C++, objects aren't reference types that default to null, so this statement is almost never correct. You probably want just A a;
A a creates a new instance of A, but the = A() part invokes A's copy constructor with a temporary default constructed A. If you had done just A a; it would have just created a new instance of A using the default constructor.
If you don't explicitly implement your own copy constructor for a class, the compiler will create one for you. The compiler created copy constructor will just make a carbon copy of the other object's data; this means that if you have any pointers, it won't copy the data pointed to.
So, essentially, that line is creating a new instance of A, then constructing another temporary instance of A with the default constructor, then copying the temporary A to the new A, then destructing the temporary A. If the temporary A is acquiring resources in it's constructor and de-allocating them in it's destructor, you could run into issues where your object is trying to use data that has already been deallocated, which is undefined behavior.
Take this code for example:
struct A {
A() {
myData = new int;
std::cout << "Allocated int at " << myData << std::endl;
}
~A() {
delete myData;
std::cout << "Deallocated int at " << myData << std::endl;
}
int* myData;
};
A a = A();
cout << "a.myData points to " << a.myData << std::endl;
The output will look something like:
Allocated int at 0x9FB7128
Deallocated int at 0x9FB7128
a.myData points to 0x9FB7128
As you can see, a.myData is pointing to an address that has already been deallocated. If you attempt to use the data it points to, you could be accessing completely invalid data, or even the data of some other object that took it's place in memory. And then once your a goes out of scope, it will attempt to delete the data a second time, which will cause more problems.
What you have implemented there is called fluent interface. I have mostly encountered them in scripting languages, but there is no reason you can't use in C++.
If you really, really hate calling lots of set functions, one after the other, then you may enjoy the following code, For most people, this is way overkill for the 'problem' solved.
This code demonstrates how to create a set function that can accept set classes of any number in any order.
#include "stdafx.h"
#include <stdarg.h>
// Base class for all setter classes
class cSetterBase
{
public:
// the type of setter
int myType;
// a union capable of storing any kind of data that will be required
union data_t {
int i;
float f;
double d;
} myValue;
cSetterBase( int t ) : myType( t ) {}
};
// Base class for float valued setter functions
class cSetterFloatBase : public cSetterBase
{
public:
cSetterFloatBase( int t, float v ) :
cSetterBase( t )
{ myValue.f = v; }
};
// A couple of sample setter classes with float values
class cSetterA : public cSetterFloatBase
{
public:
cSetterA( float v ) :
cSetterFloatBase( 1, v )
{}
};
// A couple of sample setter classes with float values
class cSetterB : public cSetterFloatBase
{
public:
cSetterB( float v ) :
cSetterFloatBase( 2, v )
{}
};
// this is the class that actually does something useful
class cUseful
{
public:
// set attributes using any number of setter classes of any kind
void Set( int count, ... );
// the attributes to be set
float A, B;
};
// set attributes using any setter classes
void cUseful::Set( int count, ... )
{
va_list vl;
va_start( vl, count );
for( int kv=0; kv < count; kv++ ) {
cSetterBase s = va_arg( vl, cSetterBase );
cSetterBase * ps = &s;
switch( ps->myType ) {
case 1:
A = ((cSetterA*)ps)->myValue.f; break;
case 2:
B = ((cSetterB*)ps)->myValue.f; break;
}
}
va_end(vl);
}
int _tmain(int argc, _TCHAR* argv[])
{
cUseful U;
U.Set( 2, cSetterB( 47.5 ), cSetterA( 23 ) );
printf("A = %f B = %f\n",U.A, U.B );
return 0;
}
You may consider the ConstrOpt paradigm. I first heard about this when reading the XML-RPC C/C++ lib documentation here: http://xmlrpc-c.sourceforge.net/doc/libxmlrpc++.html#constropt
Basically the idea is similar to yours, but the "ConstrOpt" paradigm uses a subclass of the one you want to instantiate. This subclass is then instantiated on the stack with default options and then the relevant parameters are set with the "reference-chain" in the same way as you do.
The constructor of the real class then uses the constrOpt class as the only constructor parameter.
This is not the most efficient solution, but can help to get a clear and safe API design.

C++ new[] into base class pointer crash on array access

When I allocate a single object, this code works fine. When I try to add array syntax, it segfaults. Why is this? My goal here is to hide from the outside world the fact that class c is using b objects internally. I have posted the program to codepad for you to play with.
#include <iostream>
using namespace std;
// file 1
class a
{
public:
virtual void m() { }
virtual ~a() { }
};
// file 2
class b : public a
{
int x;
public:
void m() { cout << "b!\n"; }
};
// file 3
class c : public a
{
a *s;
public:
// PROBLEMATIC SECTION
c() { s = new b[10]; } // s = new b;
void m() { for(int i = 0; i < 10; i++) s[i].m(); } // s->m();
~c() { delete[] s; } // delete s;
// END PROBLEMATIC SECTION
};
// file 4
int main(void)
{
c o;
o.m();
return 0;
}
Creating an array of 10 b's with new and then assigning its address to an a* is just asking for trouble.
Do not treat arrays polymorphically.
For more information see ARR39-CPP. Do not treat arrays polymorphically, at section 06. Arrays and the STL (ARR) of the CERT C++ Secure Coding Standard.
One problem is that the expression s[i] uses pointer arithmetic to compute the address of the desired object. Since s is defined as pointer to a, the result is correct for an array of as and incorrect for an array of bs. The dynamic binding provided by inheritance only works for methods, nothing else (e.g., no virtual data members, no virtual sizeof). Thus when calling the method s[i].m() the this pointer gets set to what would be the ith a object in the array. But since in actuality the array is one of bs, it ends up (sometimes) pointing to somewhere in the middle of an object and you get a segfault (probably when the program tries to access the object's vtable). You might be able to rectify the problem by virtualizing and overloading operator[](). (I Didn't think it through to see if it will actually work, though.)
Another problem is the delete in the destructor, for similar reasons. You might be able to virtualize and overload it too. (Again, just a random idea that popped into my head. Might not work.)
Of course, casting (as suggested by others) will work too.
You have an array of type "b" not of type "a" and you are assigning it to a pointer of type a. Polymorphism doesn't transfer to dynamic arrays.
a* s
to a
b* s
and you will see this start working.
Only not-yet-bound pointers can be treated polymorphically. Think about it
a* s = new B(); // works
//a* is a holder for an address
a* s = new B[10]
//a* is a holder for an address
//at that address are a contiguos block of 10 B objects like so
// [B0][B2]...[B10] (memory layout)
when you iterate over the array using s, think about what is used
s[i]
//s[i] uses the ith B object from memory. Its of type B. It has no polymorphism.
// Thats why you use the . notation to call m() not the -> notation
before you converted to an array you just had
a* s = new B();
s->m();
s here is just an address, its not a static object like s[i]. Just the address s can still be dynamically bound. What is at s? Who knows? Something at an address s.
See Ari's great answer below for more information about why this also doesn't make sense in terms of how C style arrays are layed out.
Each instance of B contains Both X data member and the "vptr" (pointer to the virtual table).
Each instance of A contain only the "vptr"
Thus , sizeof(a) != sizeof(b).
Now when you do this thing : "S = new b[10]" you lay on the memory 10 instances of b in a raw , S (which has the type of a*) is getting the beginning that raw of data.
in C::m() method , you tell the compiler to iterate over an array of "a" (because s has the type of a*) , BUT , s is actualy pointing to an array of "b". So when you call s[i] what the compiler actualy do is "s + i * sizeof(a)" , the compiler jumps in units of "a" instead of units of "b" and since a and b doesn't have the same size , you get a lot of mambojumbo.
I have figured out a workaround based on your answers. It allows me to hide the implementation specifics using a layer of indirection. It also allows me to mix and match objects in my array. Thanks!
#include <iostream>
using namespace std;
// file 1
class a
{
public:
virtual void m() { }
virtual ~a() { }
};
// file 2
class b : public a
{
int x;
public:
void m() { cout << "b!\n"; }
};
// file 3
class c : public a
{
a **s;
public:
// PROBLEMATIC SECTION
c() { s = new a* [10]; for(int i = 0; i < 10; i++) s[i] = new b(); }
void m() { for(int i = 0; i < 10; i++) s[i]->m(); }
~c() { for(int i = 0; i < 10; i++) delete s[i]; delete[] s; }
// END PROBLEMATIC SECTION
};
// file 4
int main(void)
{
c o;
o.m();
return 0;
}