将此作为参数传递给C ++中的成员

时间:2013-04-04 07:11:28

标签: c++

我想将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函数。

4 个答案:

答案 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()
    {
        /*...*/
    }
};