Есть два класса-потомка (A и B) от общего базового абстракта P.
class P
{
int data;
virtual foo() = 0;
}
class A: public P
{
// no class specific data, only methodsvirtual foo() { ++data; }
}
class B: public P
{
// no class specific data, only methodsvirtual foo() { --data; }
}
Есть некий конкретный instance созданный как A.
P* p = new A;
Существует ли способ сменить класс объекта в p?
Я понимаю что стандартными способами — нет.
Но в принципе это задача смены одного указателя на vtbl у объекта.
Как бы это сделать путем "наименьшего хака"?
Вот такой вот вопрос.
Re: хочу странного: сменить класс объекта в runtime
Здравствуйте, c-smile, Вы писали:
CS>Есть два класса-потомка (A и B) от общего базового абстракта P.
CS>
CS>class P
CS>{
CS> int data;
CS> virtual foo() = 0;
CS>}
CS>class A: public P
CS>{
CS> // no class specific data, only methods
CS> virtual foo() { ++data; }
CS>}
CS>class B: public P
CS>{
CS> // no class specific data, only methods
CS> virtual foo() { --data; }
CS>}
CS>
CS>Есть некий конкретный instance созданный как A.
CS>
CS>P* p = new A;
CS>
CS>Существует ли способ сменить класс объекта в p? CS>Я понимаю что стандартными способами — нет. CS>Но в принципе это задача смены одного указателя на vtbl у объекта. CS>Как бы это сделать путем "наименьшего хака"?
CS>Вот такой вот вопрос.
P* p = new B;
или я чего то не понял?
Re: хочу странного: сменить класс объекта в runtime
CS>Существует ли способ сменить класс объекта в p? CS>Я понимаю что стандартными способами — нет. CS>Но в принципе это задача смены одного указателя на vtbl у объекта. CS>Как бы это сделать путем "наименьшего хака"?
pimpl, handle/body, делегация?
Re[2]: хочу странного: сменить класс объекта в runtime
Здравствуйте, Awaken, Вы писали:
CS>>Существует ли способ сменить класс объекта в p? CS>>Я понимаю что стандартными способами — нет. CS>>Но в принципе это задача смены одного указателя на vtbl у объекта. CS>>Как бы это сделать путем "наименьшего хака"?
A>pimpl, handle/body, делегация?
+1. И всё это, взятое вместе, называется паттерном State.
Re[2]: хочу странного: сменить класс объекта в runtime
Здравствуйте, Awaken, Вы писали:
CS>>Существует ли способ сменить класс объекта в p? CS>>Я понимаю что стандартными способами — нет. CS>>Но в принципе это задача смены одного указателя на vtbl у объекта. CS>>Как бы это сделать путем "наименьшего хака"?
A>pimpl, handle/body, делегация?
Эти слова я знаю. Плюсы и минусы тоже знаю. Все эти подходы определяют новые сущности.
Мысли вслух:
Хочется простой вещи типа:
P* p = new A;
new(p) B;
Надо по-эксперементировать ...
Re[3]: хочу странного: сменить класс объекта в runtime
Здравствуйте, c-smile, Вы писали:
CS>Здравствуйте, Awaken, Вы писали:
CS>>>Существует ли способ сменить класс объекта в p? CS>>>Я понимаю что стандартными способами — нет. CS>>>Но в принципе это задача смены одного указателя на vtbl у объекта. CS>>>Как бы это сделать путем "наименьшего хака"?
A>>pimpl, handle/body, делегация?
CS>Эти слова я знаю. Плюсы и минусы тоже знаю. Все эти подходы определяют новые сущности.
CS>Мысли вслух:
CS>Хочется простой вещи типа:
CS>
CS>P* p = new A;
CS>new(p) B;
CS>
CS>Надо по-эксперементировать ...
Может проще будет создать 2 объекта сразу ?
P* f(bool need_a)
{
static A a;
static B b;
return need_a ? &a : &b;
}
Здравствуйте, c-smile, Вы писали:
CS>Существует ли способ сменить класс объекта в p? CS>Я понимаю что стандартными способами — нет. CS>Но в принципе это задача смены одного указателя на vtbl у объекта. CS>Как бы это сделать путем "наименьшего хака"? CS>Вот такой вот вопрос.
Вот эта вот кострукция компилируется на ура и делает то что надо:
#include"new.h"struct P
{
int data;
P() {}
virtual ~P() {}
virtual foo() = 0;
};
template <typename T>
inline P* ctor(int d) { P* t = new T; t->data = d; return t; }
template <typename T>
inline void turn_to(P* p) { ::new(p) T; }
struct A: public P
{
// no class specific data, only methodsvirtual foo() { ++data; }
};
struct B: public P
{
// no class specific data, only methodsvirtual foo() { --data; }
};
int main(int argc, char* argv[])
{
P *p = ctor<A>(0);
p->data = 0;
p->foo();
printf("step 1, p.data = %d\n", p->data);
turn_to<B>(p);
p->foo();
printf("step 2, p.data = %d\n", p->data);
return 0;
}
Проверяю дальше.
Re[2]: хочу странного: сменить класс объекта в runtime
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
template<class TFrom, class TTo> void SwitchTo( P* p )
E>{
E> static_assert( sizeof( TFrom ) >= sizeof( TTo ) );
E> assert( dynamic_cast<TFrom*>( p ) != 0 );
p->~P();
E> new( p ) TTo;
E> assert( dynamic_cast<TTo*>( p ) != 0 );
E>}
E>
Мне p->~P(); как раз не нужен.
Мне нужно переключить behavior класса в зависимости от некоего условия.
Операции конструирования и копирования объектов достаточно дорогие.
Поэтому все что я могу себе позволить это переключить vtbl
E>Вроде даже без UB всюду...
Не вижу я там UB. TFrom и TTo ничего не добавляют в instance.
Отличие этих классов сугубо в vtbl.
Re[3]: хочу странного: сменить класс объекта в runtime
namespace html
{
struct element
{
... data ...
void do_layout() = 0;
};
struct paragraph : public element
{
void do_layout() { layout as a text container };
};
struct div : public element
{
void do_layout() { layout as a block container };
};
}
Каждый элемент в зависимости от CSS атрибута:
display-model: block-inside | inline-inside | table
должен переключать способ do_layout и чертову силу других методов.
Причем display-model может переключаться динамически (во всяком случае это не запрещено)
Вот такие вот пироги. Два (5 на самом деле) объекта создавать само собой я даже и не знаю как.
Re[4]: хочу странного: сменить класс объекта в runtime
[]
CS>Мне p->~P(); как раз не нужен.
CS>Мне нужно переключить behavior класса в зависимости от некоего условия. CS>Операции конструирования и копирования объектов достаточно дорогие. CS>Поэтому все что я могу себе позволить это переключить vtbl
Только зачем это делать, рискуя нарваться на неприятности с placement new?
Здравствуйте, c-smile, Вы писали:
CS>Есть два класса-потомка (A и B) от общего базового абстракта P.
ну первое это vtab вручную — поместить в класс указатели на методы.
Просто переписать vtab по адресу (viud *(&))(*this)
placement new — воспользоватся раздельной компиляцией и описать одноименный пустой класс без всяких data только обьявления виртуальных методов в томже порядке. И public на те классы где есть виртуальные методы. Тогда по идее структура vtabl сохранится, а побочного ффекта от конструкторов-деструкторов не будет
Описать сначала невиртуальные методы, потом перекрыть (продублировать) ихже виртуальными, тогда можно вернутся к той базе где виртуальных нет
Здравствуйте, c-smile, Вы писали:
CS>Мне нужно переключить behavior класса в зависимости от некоего условия. CS>Операции конструирования и копирования объектов достаточно дорогие. CS>Поэтому все что я могу себе позволить это переключить vtbl
Здравствуйте, c-smile, Вы писали:
CS>должен переключать способ do_layout и чертову силу других методов.
CS>Причем display-model может переключаться динамически (во всяком случае это не запрещено)
Читать "Паттерны проектирования". Решение твоей проблемы — паттерн State, вероятнее всего тебе также понадобятся Factory method и Composite.
В vtbl лезть не стоит.
Re[6]: хочу странного: сменить класс объекта в runtime
Здравствуйте, gandjustas, Вы писали:
G>Здравствуйте, c-smile, Вы писали:
CS>>должен переключать способ do_layout и чертову силу других методов.
CS>>Причем display-model может переключаться динамически (во всяком случае это не запрещено)
G>Читать "Паттерны проектирования". Решение твоей проблемы — паттерн State, вероятнее всего тебе также понадобятся Factory method и Composite.