【发布时间】:2011-11-17 23:51:58
【问题描述】:
class base {
int a;
protected:
template<class T>
class derived;
public:
base() {}
virtual ~base() {}
virtual void func() {}
static base* maker();
};
template <class T>
class base::derived
: public base
{
public:
derived() {}
virtual ~derived() {}
virtual void func() {
this->~derived(); //<--is this legal?
new (this) derived<int>(); //<--is this legal?
}
};
base* base::maker() {
return new derived<double>();
}
int main() {
base* p = base::maker(); //p is derivedA<double>
p->func(); //p is now derivedA<int>
delete p; //is the compiler allowed to call ~derived<double>()?
}
这是我的代码的简短、自包含、正确(可编译)示例(基本上是为了我自己的成长而重新发明any_iterator)。
问题归结为:当共享基数上没有任何其他成员时,销毁this 并使用从同一基数虚拟派生的不同类型重构this 是否是未定义的行为?具体来说,编译器是否允许调用静态类型的跟踪,或者这在技术上不符合标准?
[编辑] 一些人指出,如果在堆栈上创建 derivedA,编译器可能会调用不正确的析构函数。 (1) 我在标准中找不到任何允许编译器这样做的东西。 (2) 除了我的问题打算之外,我已经更改了代码以显示derived 不能放在堆栈上。 base 仍然可以在堆栈中。
【问题讨论】:
-
正确与否无关紧要。头脑正常的人不会这样做。即使它确实有效,也将是维护的噩梦,因此它永远不会在实际代码中发生。
-
离题:为什么要转换成巨大的指针? Placement-new 需要一个 void 指针。也许您的案例是动态转换为无效的候选者!
void * p = dynamic_cast<void*>(this); new (p) T; -
我很确定如果用于堆栈上声明的变量,这会严重破坏。
-
@KerrekSB 我是否感觉到您正试图从本周早些时候从一个问题中学到的东西中获得乐趣? :)
-
@MatteoItalia:不,这完全没问题(见我的回答)。 w00te:有那么一分钟,我以为我们可能会在这里做点什么,但现在我确信它没有任何意义:-(
标签: c++ templates virtual placement-new