I have a problem related to designing derived classes with array parameters. I have class B derived from A. And class BB derived from AA with array of B and A respectively...
#include <iostream>
class A
{
public:
A(){}
virtual void foo(){std::cout<<"foo A\n";}
int idx[3];
};
class B: public A
{
public:
B():A(){}
void foo(){std::cout<<"foo B\n";}
int uidx[3];
};
class AA
{
public:
AA(){}
AA(int count){
m_count = count;
m_a = new A[count];
}
virtual A* getA(){return m_a;}
~AA(){ delete[] m_a;}
protected:
A* m_a;
int m_count;
};
class BB: public AA
{
public:
BB(int count):AA()
{
m_count = count;
m_a = new B[count];
}
B* getA(){return dynamic_cast<B*>(m_a);}
};
int main()
{
AA* aa = new AA(2);
BB* bb = new BB(2);
B* b = bb->getA();
B& b0 = *b;
b0.idx[0] = 0;
b0.idx[1] = 1;
b0.idx[2] = 2;
B& b1 = *(b+1);
b1.idx[0] = 2;
b1.idx[1] = 3;
b1.idx[2] = 4;
std::cout<<bb->getA()[1].idx[0]<<"\n"; //prints 2
std::cout<<bb->getA()[1].idx[1]<<"\n"; //prints 3
std::cout<<bb->getA()[1].idx[2]<<"\n"; //prints 4
AA* cc = static_cast<AA*>(bb);
cc->getA()[0].foo(); //prints foo B
std::cout<<cc->getA()[1].idx[0]<<"\n"; //prints 4198624 ??
std::cout<<cc->getA()[1].idx[1]<<"\n"; //prints 0 ??
std::cout<<cc->getA()[1].idx[2]<<"\n"; //prints 2 ??
cc->getA()[1].foo(); //segmentation fault
delete aa;
delete bb;
return 0;
}
After static cast BB to AA I can't access A's with indices more then 0.
How to solve this issue?
Thank you.
Note that cc->getA() is semantically equal to cc->A::getA() (not cc->B::getA()) and returns a pointer to A (instead of B*).
Now, since A is the subclass of B, but the latter also includes some extra fields, then sizeof(B) > sizeof(A). Since cc->getA()[n] is basically *(cc->getA() + n) the line
cc->getA()[1].foo();
does the same thing as:
A * const tmp = cc->getA();
A & tmp2 = *(tmp + 1); // sizeof(A) bytes past tmp
tmp2.foo();
which causes undefined behaviour due to §5.7.6 [expr.add] of the C++ standard which states:
For addition or subtraction, if the expressions P or Q have type “pointer to cv T”, where T and the array element type are not similar ([conv.qual]), the behavior is undefined. [ Note: In particular, a pointer to a base class cannot be used for pointer arithmetic when the array contains objects of a derived class type. — end note ]
You probably wanted behaviour similar to the following:
A * const tmp = cc->getA();
A & tmp2 = *(static_cast<B *>(tmp) + 1); // sizeof(B) bytes past tmp
tmp2.foo();
For that you need to use something like:
std::cout<<static_cast<B*>(cc->getA())[1].idx[0]<<"\n"; // prints 2
std::cout<<static_cast<B*>(cc->getA())[1].idx[1]<<"\n"; // prints 3
std::cout<<static_cast<B*>(cc->getA())[1].idx[2]<<"\n"; // prints 4
static_cast<B*>(cc->getA())[1].foo(); // prints foo B
However, it is better to implement a virtual A & operator[](std::size_t) operator for AA and override it in BB.
I can see 2 issues in your code:
Since your classes are responsible for memory management, I would suggest to make your destructors virtual, because if you, at any point, will try to delete derived class object via base pointer, the destructors of derived classes will not be invoked. It shouldn't be a problem in your current code, but may become a problem in a future.
I.e:
int main ()
{
AA* aa = new BB (2);
delete aa;
}
Will not call the BB::~BB() in your case.
The problem that you are noticing, and writing this question about.
After you cast your variable of type from BB* to AA* (even though, the cast isn't necessary, you can straight-up assign, due to types being covariant) in line:
AA* cc = dynamic_cast<AA*>(bb);
Your variable cc is treated as if it is of type AA* (it doesn't matter that it has the runtime type of BB*, in general case - you don't know, and should not care about the exact runtime type). On any virtual method call, they are dispatched to the correct type via the use of the vtable.
And now, why are you getting strange values printed in the console/segmentation fault? What's the result of cc->getA ()? Since the variable cc is treated as AA*, the return value is A* (as explained above, actual type is B*, but, due to is-a relationship of inheritance is treated as A*). What's the problem, you may ask: The array m_a is the same size in both cases, right?
Well, not really, to explain that, I would need to explain how array indexing works in C++, and how it is related to sizes of the objects.
I guess, that I wouldn't shock you, stating that size of object of type B (sizeof (B)), is larger than that of type A (sizeof (A)), since B has everything that A has (due to inheritance), with some stuff of its own. On my machine sizeof(A) = 16 bytes, and sizeof(B) = 28 bytes.
So, when you create an array, the total amount of space that array takes up is [element_count] * [size of the element] bytes, which seems logical. But, when you need to take an element from an array, it needs to figure, where exactly, that element is, in the memory, in all the space that array is taking up, so it does so, by calculating it. It does so as follows: [start of the array] + [index] * [size of element].
And, now we arrive at the source of the problem. You are trying to do cc->getA ()[1], but, since cc, under the hood, is BB*, so the size of AA::m_a variable is 2 * sizeof (B) (= 2 * 28 = 56 on my machine; first objects starts at offset 0 (0 * sizeof (B); second at offset 28 (1 * sizeof(B))), but since cc->getA () gets treated as A*, and you are trying to fetch second element from the array (index 1), it tries to fetch the object from the offset of1 * sizeof (A)`, which, unfortunately, is in the middle of the space reserved to an object, and yet, any values can be printed/anything can happen - undefined behavior is invoked.
How to fix it? I would fix it by implementing the virtual indexing operators, instead of GetA method on classes AA/BB, as follows:
class AA
{
public:
...
virtual A& operator[] (int idx)
{
return m_a[idx];
}
...
};
class BB : public AA
{
public:
...
virtual B& operator[] (int idx)
{
return dynamic_cast<B*>(m_a)[idx];
}
...
};
But, then you would need to be careful to call the operator on the object itself, and not to a pointer to object:
std::cout << cc->operator[](1).idx[0] << "\n";
std::cout << cc->operator[](1).idx[1] << "\n";
std::cout << cc->operator[](1).idx[2] << "\n";
Related
I have to make an array of pointers that point to type B objects and that array must be an attribute of
class A. When I am trying to print the code of B I am getting no result.
In main() I am trying to call for D object the getBobj method that returns a pointer at a B object and then call the getCode() method to get and print the code.
class B
{
string code;
public:
.
.
.
B(int i)
{
code = i;
}
string getCode ()
{
return code;
}
.
.
.
};
class A
{
int numOfB;
B **objB;
public:
void setBobj (const A *obj_a, B *obj_b_arr)
{
delete [] objB;
objB = new B * [obj_a->getNumOfBobj()];
memcpy (objB, obj_b_arr, obj_a->getNumOfBobj());
}
B * A::getBobj (const A &obja)
{
return *objB;
}
};
int main ()
{
.
.
.
.
B b1(1);
B b2(2);
B b3(3);
B b[] = {b1, b2, b3};
D.setBobj(&D, &b);
cout << (D.getBobj(D))->getCode(); //Nothing gets printed
}
objB = new B * [obj_a->getNumOfBobj()];
memcpy (objB, obj_b_arr, obj_a->getNumOfBobj());
This is (probably) wrong. You are allocating an array of the size of the previous number of Bobjs in A when setting a new array. You probably meed to pass in the number of Bs to setBobj.
Also, this is an unholy mess of C and C++ style coding. You probably want a vector instead of raw allocated arrays, and use std::copy instead of memcpy, etc.
Also you either need to make your functions static or even better, don't pass in the address of D when calling setBobj/getBObj - just use this.
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.
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).
I am trying to access member variables of a class without using object. please let me know how to go about.
class TestMem
{
int a;
int b;
public:
TestMem(){}
void TestMem1()
{
a = 10;
b = 20;
}
};
void (TestMem::*pMem)();
int main(int argc, char* argv[])
{
TestMem o1;
pMem = &(TestMem::TestMem1);
void *p = (void*)&pMem;
// How to access a & b member variables using variable p
getch();
return 0;
}
The "right" way to do this is by using the offsetof() macro from <stddef.h>. Unfortunately offsetof() has some fairly draconian restrictions in C++:
Because of the extended functionality of structs in C++, in this language, the use of offsetof is restricted to "POD [plain old data] types", which for classes, more or less corresponds to the C concept of struct (although non-derived classes with only public non-virtual member functions and with no constructor and/or destructor would also qualify as POD).
So if you make a and b public and get rid of TestMem's constructor, you can write something like this to access a:
C++ style:
#include <cstddef>
int vala = *reinterpret_cast<int *>(reinterpret_cast<char *>(&o1)
+ offsetof(TestMem, a));
C style:
#include <stddef.h>
int vala = *(int *) ((char *) &o1 + offsetof(TestMem, a));
Notice that you need to use &o1 here, not p, which is a function pointer. The address of TestMem::TestMem1 won't have any relation to the locations of a and b. Class methods don't reside in memory anywhere near class member variables.
The "wrong" way is to just guess at where a and b are in memory. Most likely they are at offsets 0 and 4 from the start of o1, respectively. So this code would work most of the time:
int vala = *(int *) ((char *) &o1 + 0);
int valb = *(int *) ((char *) &o1 + 4);
There are a lot of assumptions here. This assumes that ints are 4 bytes and that there's no padding between a and b. On the other hand it doesn't have any of the restrictions from above: a and b don't need to be public, you can have a constructor, whatever.
Simple answer: Don't do it.
There just can not be any situation where you can justify accessing like this. There just has to be a different solution.
I came up with a solution but it's dirty:
class TestMem
{
public:
int a;
int b;
TestMem(){}
void TestMem1()
{
a = 10;
b = 20;
}
};
void* offset(void* ptr, ...)
{
va_list ap;
va_start(ap, ptr); // get 1st argument's address
long i = va_arg(ap, long); // get next argument
va_end(ap);
return (char*)ptr + i;
}
void test()
{
TestMem t;
void* p = (TestMem*)&t;
t.a = 8;
t.b = 9;
printf("%i\n", *(int*)offset(p, &TestMem::a));
printf("%i\n", *(int*)offset(p, &TestMem::b));
}
I wanted to comment the answer provided by John Kugelman, being a new member didn't have enough reputation, hence posting it like an answer.
offsetof - is a C function used with structures where every member is a public, not sure whether we can refer the private variables as referred in the answer.
However the same can be achieved replacing the offsetof with a simple sizeof, ofcourse when we are sure of the type of the data members.
int vala = *reinterpret_cast<int *>(reinterpret_cast<char *>( ptr ) );
int valb = *reinterpret_cast<int *>(reinterpret_cast<char *>( ptr ) + sizeof ( int ) );
To my knowledge, you wouldn't be able to access.
By the time you have assigned p, it doesn't refer to o1 here and
p cannot replace pMem in (o1.*pMem)(), as p is not defined as function member to TestMem.
Short answer: You can't.
Long answer: You can, but it's highly implementation dependent.
If you dump the memory you find at *p you'll see, somewhere around there, what you're looking for - a and b. But you will very likely also see some other stuff. What that stuff is, what it means, how big it is (and by implication where a and b actually live) is implementation dependent.
There totally is a way. C++ has member pointers, pointers relative to an object. They are defined by prefixing T:: to the * on the pointer type, and used by using the ->* or .* member pointer access operators. So yeah, it looks horrible :).
class T {
int a, b;
public:
typedef int T::* T_mem_ptr_to_int;
static T_mem_ptr_to_int const a_ptr;
static T_mem_ptr_to_int const b_ptr;
};
T::T_mem_ptr_to_int const T::a_ptr = &T::a;
T::T_mem_ptr_to_int const T::b_ptr = &T::b;
int weird_add(T* left, T* right) {
return left->*T::a_ptr + right->*T::b_ptr;
}
This is used much more often for member function pointers, which look like Result (T::*ptr_name)(Arg1, Arg2, ...).
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;
}