Reputation: 166
class A
{
public:
int a;
};
class B:public A
{
public:
int b;
void foo()
{
b=a*a;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
A * a=new A;
a->a=10;
((B*)a)->foo();
cout<<((B*)a)->b;
}
It's working for b=100
, but I dont know by which rules it works. Where is b
stored? I just don't know how its called to google it.
Upvotes: 2
Views: 143
Reputation: 18019
@anderas has provided a very good explanation why the behavior is undefined.
Here is a relevant clause from the standard (n4431, emphasis mine):
11 ...
If the rvalue of type “pointer to cv1 B” points to a B that is actually a sub-object of an object of type D, the resulting pointer points to the enclosing object of type D. Otherwise, the result of the cast is undefined.
[expr.static.cast]
So, the cast in your code is undefined.
The following would work:
class A
{
public:
int a;
virtual void foo() = 0; // make it polymorphic
};
class B:public A
{
public:
int b;
virtual void foo()
{
b=a*a;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
A * a=new B; // create an instance of B
a->a=10;
((B*)a)->foo();
cout<<((B*)a)->b;
// don't forget to delete 'a'
}
Upvotes: 2
Reputation: 3974
Your code will lead to 2 undefined behaviour:
A
as a B
.b
(this variable does not exist
in memory).Here is pontential implementation to use an instance of B as a pointer of A.
class A
{
public:
void setA(int aToSet)
{
a = aToSet;
}
virtual void foo() = 0;
virtual void getResult() const = 0;
private:
int a;
};
class B : public A
{
public:
void foo() override
{
b = a * a;
}
void getResult() const override
{
return b;
}
private:
int b;
};
int _tmain(int argc, _TCHAR* argv[])
{
A *a = new B();
a->setA(10);
a->foo();
cout << a->getResult();
}
Upvotes: 0
Reputation: 5854
Basically, what is happening here is undefined behaviour. It doesn't have a special name; most likely it is called a programming mistake. The memory layout of your class A
is:
int a;
The memory layout of B
is:
int a;
int b;
So in your case, you only allocate space for a
but you are lucky that the space immediately after it is free (so that no other information is overwritten) and that it doesn't border on unallocated space (otherwise, a fault might occur when trying to write to an unallocated page). So b
is stored in free space.
In short: don't rely on this code to work!
Upvotes: 6
Reputation: 234875
The behaviour is undefined. You can only cast a
to B*
if it is a pointer to a B
.
Don't do this.
You couldn't even write A* a = new B;
followed by (dynamic_cast<B*>(a))->foo();
since the classes are not polymorphic types.
Upvotes: 2