Re: Constructing Derived in shell of Base <shudder>
On 7/13/2010 4:35 PM, Kenneth 'Bessarion' Boyd wrote:
On Jul 13, 1:47 pm, Victor Bazarov<v.baza...@comcast.invalid> wrote:
Well, "messing with its storage" should in this case be enough because
the expression 'new (&b) Derived' is supposed to *construct* the Derived
object in the memory that 'b' occupies. The act of construction of that
object *should* include setting up the virtual function resolution
mechanism properly for the call to 'b.f()' *if* 'b' were a reference. ....
Right.
Here is the fixed program, which works "as the OP expected":
This...I'm not sure sure it works as expected, or merely works by
common empirical facts about implementations.
#include<iostream>
#include<memory>
struct B { int j; virtual void f() { std::cout<< "B::f\n"; } };
struct D : B { virtual void f() { std::cout<< "D::f\n";} };
int main()
{
B b;
B& rb = b;
rb.f(); // B::f() invoked
b.~B();
/* undefined behavior when sizeof(B)<sizeof(D)
'When' is the key word. The OP started with the premise that the sized
*are* the same. So, no UB.
* we are also gambling that the memory requirement indicated
* by sizeof is actually contiguous, but I haven't even seen
specs
* for such exotic hardware so don't worry about that.
Uh... Objects are defined to occupy contiguous storage. What specs for
what exotic hardware?
* Cause a compile error for this; C++0X would use
static_assert. */
Huh?
typedef B_D_same_size[sizeof(B)>=sizeof(D) ? 1 : -1];
new (&b) D; // create D in shell of B
rb.f(); // D::f() invoked
// ~B() invoked at end of scope on object intended to be of type
D: do we get lucky?
The destructor of the D object created in 'B' by means of placement new,
has to be directly invoked (using the same syntax). And the second
invocation of B::~B has to be prevented since it was invoked already
earlier...
}
How about the following?
int main()
{
unsigned char buffer[sizeof(B)>=sizeof(D) ? sizeof(B) :
sizeof(D)];
B* b = new (buffer) B;
b->f(); // B::f() invoked
b->~B();
b = new (buffer) D;
b->f(); // D::f() invoked
static_cast<D*>(b)->~D();
That's fine. Not the original question, but fine.
}
[The main context where I have considered using such gymnastics, is
reimplementing the STL. There's some a priori sense in being able to
make the node-type backing classes be derived from raw structs that
actually can use C memory management.]
Why were you considering reimplementing STL? Exercise?
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask