Здравствуйте, c-smile, Вы писали:
CS>Контекст проблемы: http://stackoverflow.com/questions/21212379/changing-vtbl-of-existing-object-on-the-fly-dynamic-subclassing
А если не выклёвывать себе мозг всякими трюками, и сделать по-честному:
struct Operand;
// ООП (паттерн Стратегия)
struct IOperator
{
virtual void doit(Operand& operand) const = 0;
virtual const char* whoami() const = 0;
};
// Си или ФП
struct OperatorVTBL
{
void (*doit)(Operand& operand);
const char* (*whoami)();
const char* itsme;
};
struct Operand
{
int f1, f2;
IOperator* op; // так
OperatorVTBL* vp; // этак
void doit() { op->doit(*this); }
const char* whoami() const { return op->whoami(); }
};
struct Summator : IOperator
{
void doit(Operand& operand) { operand.f1 += operand.f2; }
const char* whoami() const { return "+"; }
} summator_v1;
OperatorVTBL summator_v2 = {
[](Operator& operand)->void { operand.f1 += operand.f2; },
[]()->const char* { return "+"; },
"+",
};
Сишный способ даёт на одну косвенность меньше. А если в интерфейсе только одна функция, то можно вообще сразу эту функцию присваивать (предельный случай идиомы NVI).
Ну и наконец, маленький, но странный хак. Срезка наооборот.
#include <cstdio>
#include <memory>
struct Base
{
int x, y, z;
Base(int i) : x(i), y(i+i), z(i*i) {}
virtual void whoami() { printf("%p base %d %d %d\n", this, x, y, z); }
};
struct Derived : Base
{
Derived(Base&& b) : Base(b) {}
virtual void whoami() { printf("%p derived %d %d %d\n", this, x, y, z); }
};
int main()
{
Base b(3);
Base* p = &b;
b.whoami(); // 000000000022fd50 base 3 6 9
p->whoami(); // 000000000022fd50 base 3 6 9
Base t(std::move(b));
Derived* d = new(&b)Derived(std::move(t));
printf("-----\n");
b.whoami(); // 000000000022fd50 base 3 6 9
p->whoami(); // 000000000022fd50 derived 3 6 9
d->whoami(); // 000000000022fd50 derived 3 6 9
};
Обрати внимание, что компилятор не ждёт подлянки с подменой типа и немножко оптимизирует.