Re[3]: С++, как вызвать конструктор объекта по месту?
От: Кодт Россия  
Дата: 21.01.14 12:14
Оценка:
Здравствуйте, 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
};

Обрати внимание, что компилятор не ждёт подлянки с подменой типа и немножко оптимизирует.
Перекуём баги на фичи!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.