gpt4 book ai didi

c++ - 更改现有对象 "on the fly"的 VTBL,动态子类化

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:37:55 24 4
gpt4 key购买 nike

考虑以下设置。

基类:

class Thing {
int f1;
int f2;

Thing(NO_INIT) {}
Thing(int n1 = 0, int n2 = 0): f1(n1),f2(n2) {}
virtual ~Thing() {}

virtual void doAction1() {}
virtual const char* type_name() { return "Thing"; }
}

和派生类不同通过上述方法的实现:

class Summator {
Summator(NO_INIT):Thing(NO_INIT) {}

virtual void doAction1() override { f1 += f2; }
virtual const char* type_name() override { return "Summator"; }
}

class Substractor {
Substractor(NO_INIT):Thing(NO_INIT) {}
virtual void doAction1() override { f1 -= f2; }
virtual const char* type_name() override { return "Substractor"; }
}

我的任务需要能够即时更改现有对象的类(在本例中为 VTBL)。如果我没记错的话,这就是所谓的动态子类化。

所以我想出了以下功能:

// marker used in inplace CTORs
struct NO_INIT {};

template <typename TO_T>
inline TO_T* turn_thing_to(Thing* p)
{
return ::new(p) TO_T(NO_INIT());
}

that 就是这样做的 - 它使用 inplace new 来构造一个对象来代替另一个对象。实际上,这只是更改了对象中的 vtbl 指针。所以这段代码按预期工作:

Thing* thing = new Thing();
cout << thing->type_name() << endl; // "Thing"
turn_thing_to<Summator>(thing);
cout << thing->type_name() << endl; // "Summator"
turn_thing_to<Substractor>(thing);
cout << thing->type_name() << endl; // "Substractor"

我对这种方法唯一的主要问题是a) 每个派生类都应具有特殊的构造函数,例如 Thing(NO_INIT) {},它们将完全不执行任何操作。 b) 如果我想向 Thing 添加像 std::string 这样的成员,它们将不起作用 - 只有本身具有 NO_INIT 构造函数的类型才被允许作为 Thing 的成员。

问题:对于解决“a”和“b”问题的这种动态子类化,是否有更好的解决方案?我觉得 std::move 语义可能有助于以某种方式解决 'b' 但不确定。

这是 ideone的代码。

最佳答案

(已在 RSDN http://rsdn.ru/forum/cpp/5437990.1 回答)

有一个棘手的方法:

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();
p->whoami();

assert(sizeof(Base)==sizeof(Derived));
Base t(std::move(b));
Derived* d = new(&b)Derived(std::move(t));

printf("-----\n");
b.whoami(); // the compiler still believes it is Base, and calls Base::whoami
p->whoami(); // here it calls virtual function, that is, Derived::whoami
d->whoami();
};

当然是UB。

关于c++ - 更改现有对象 "on the fly"的 VTBL,动态子类化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21212379/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com