我想将this
作为参数传递给成员变量,如下所示:
template<class T>
struct fun
{
fun(T* pointer) : memberPointer(pointer)
{
}
T* memberPointer;
};
struct gun
{
gun() : member(this)
{
}
fun<gun> member;
};
在Visual Studio中,我有下一个警告:warning C4355: 'this' : used in base member initializer list
你能解释为什么这样做是错的?我只是将指针存储在成员构造函数中,以便稍后使用它从gun
调用一些fun
函数。
答案 0 :(得分:5)
潜在的问题是this
指向尚未完全构造的对象。例如,如果你有这个:
template<class T>
struct fun
{
fun(T* pointer) : memberPointer(pointer)
{
memberPointer->callMethod(); //this is 2nd to execute
}
T* memberPointer;
};
struct gun
{
gun() : member(this) //this is 1st to execute
{
ptr = new char(); // this is 4rd to execute unless earlier UB prevents execution
}
void callMethod()
{
printf("%s", ptr); //this is 3rd to execute, you get UB here
}
fun<gun> member;
char* ptr;
};
您将遇到未定义的行为,因为您将指针传递给未完全构造的对象,其中只应传递指向完全构造的对象的指针。我故意用UB制作一些糟糕的代码以使其更具说服力,在现实生活中你不一定会将UB作为一个问题,有时所有对象都将处于有效状态,因此你会得到一些非常微妙的初始化命令错误。
那不是你的情况。你的情况很好 - 你不关心对象还没有完全构建。但是,在更改代码时应该小心,这样就不会进入上面的场景。
答案 1 :(得分:1)
这只是一个警告。如果您在有趣的构造函数中使用deference this
,那么您将访问未初始化的对象。但你不是,你只存储指针,所以你可以忽略警告。如果您想关闭警告,请在代码顶部添加
#pragma warning (disable: 4355)
答案 2 :(得分:0)
这并非完全错误,但是当您传递指针时,您的枪支对象可能尚未完全构建。因此,可能会在基类中调用依赖于对象的完整构造的方法。
答案 3 :(得分:0)
你想要的是实现静态多态,最好通过curiously recurring template pattern (CRTP)来处理。在你的情况下,你几乎就在那里:
template<class Base>
struct fun : public Base
{
void foo()
{
// call gun function
Base::bar();
}
};
struct gun : public fun<gun>
{
void bar()
{
/*...*/
}
};