是否可以默认传递“this”?

时间:2016-05-15 20:17:05

标签: c++ parameter-passing this

默认情况下是否可以通过this

这是我目前拥有的

class A
{
public:
    template<typename T>
    void dowithT(T t) {}
};

class B
{
public:
    A a;

    B()
    {
        //Calling 'dowithT' with 'this'
        a.dowithT(this);
    }
};

此函数每次都需要从函数的调用者传递this。所以我想知道是否有办法封装此任务,因此您无需将this传递给dowithT

我试着这样做:

class A
{
public:
    // '= this' doesn't compile
    template<typename T>
    void dowithT(T t = this) {}
};

class B
{
public:
    A a;

    B()
    {
        //Calling 'dowithT' without 'this'
        a.dowithT();
    }
};

不幸的是,我不能使用模板,所以我的第一个解决方案不是一个选项。

这可能吗?

编辑:我在下面给出了我自己实现的具体答案。还有一些我最终想要的东西。

8 个答案:

答案 0 :(得分:3)

TL; DR 不,这是不可能的。

this在每个类中都不是同一类型,你不能概括它,所以不,不可能。

此外,如果从非成员函数调用thisdoWithT()会是什么? nullptr

这就是为什么不可能的原因。您必须使用template

答案 1 :(得分:3)

而不是B拥有A类型的成员,它可以A继承,并使用类似于"curiously recurring template pattern."

如果你不能把A类作为模板,你仍然可以这样做:

class A
{
    protected:
    template <class T>
    void dowithT()
    {
         T* callerthis = static_cast<T*>(this);
         // callerthis is the "this" pointer for the inheriting object
         cout << "Foo";
    }
};

class B : public A
{
    public:
    B()
    {
        dowithT<B>();
        // Or A::dowithT<B>();
    }
};

dowithT()只能由继承类调用(因此我将其设为protected),模板参数是调用者自己的类型,否则你将破坏所有内容。

答案 2 :(得分:1)

不,这是不可能的。 this用作T*(模板与否)的函数的参数时,没有什么特别之处,它只是一个像其他任何指针一样的指针。

答案 3 :(得分:1)

this Athis B不同。在您的第一个代码中,this指的是来电者,而第二个this指的是callee。因此,你想做的事情确实是不可能的。

答案 4 :(得分:1)

这是一种可能性,可能或可能不适合您的需求:

template<typename T>
class A
{
public:
    A(T t) : t(t) {}

    void dowithT()
    {
         cout << "Foo";
    }

private:
    T t;
};

class B
{
    public:
    A<B*> a;

    B() : a(this)
    {
        a.dowithT();
    }
};

答案 5 :(得分:1)

使用私有mixin类提供不带参数的dowithT方法,你可以完全达到你想要的效果:

#include <iostream>
#include <typeinfo>

class A
{
public:
    template<typename T>
    void dowithT(T* t) {
      std::cout << "Hello, World" << typeid(*t).name() << std::endl;
    }
};

template<class Owner>
  struct calls_a
  {
    void dowithT()
    {
      auto p = static_cast<Owner*>(this);
      p->a.dowithT(p);
    }
  };

class B
  : private calls_a<B>
{
    friend calls_a<B>;
    A a;

public:
    B()
    {
        //Calling 'dowithT' with 'this'
        dowithT();
    }
};

int main()
{
  B b;

}

答案 6 :(得分:0)

你可以在B类中使用一个充当中继的私有方法,如果你想传递其他值,可以使用常量nullptr作为特殊值:

class B
{
public:
    A a;

    B()
    {
        //Calling 'dowithT' with 'this'
        innerdo();
    }
private:
    void innerdo(B *p = nullptr) {
        if (p == nullptr) p = this;
        a.dowithT(p);
    }
};

如果您只需要传递this,那就更简单了

    void innerdo() {
        a.dowithT(this);
    }

答案 7 :(得分:0)

在尝试了你提到的各种事情之后,我想自己给出答案/解决方案,以澄清一些细节:

#include <iostream>
using namespace std;

#include <functional>

template <typename CallerType>
class AFunctionConstructor{
private:
    virtual void abstr()
    {}
public:

    typedef void(CallerType::*CallerTypeFunc)();

    function<void()>* constructFunction(CallerTypeFunc func)
    {
        CallerType* newMe = dynamic_cast<CallerType*> (this);
        return new function<void()>(std::bind(func,newMe));
    }       
};

class A : public function<void()>
{
protected:


public:
    A();
    A(function<void()>* func) : function<void()>(*func)
    {}

};


//  now create ressource classes
//  they provide functions to be called via an object of class A

class B : public AFunctionConstructor<B>
{
    void foo()
    {
        cout << "Foo";
    }

public:
    A a;

    B() : a(constructFunction(&B::foo)) {}
};

class C : public AFunctionConstructor < C >
{
    void bar()
    {
        cout << "Bar";
    }

public:
    A a;

    C() : a(constructFunction(&C::bar)) {}
};

int main()
{
    B b;
    C c;

    b.a(); 
    c.a();

    cout << endl;

    A* array[5];

    array[0] = &b.a;        //different functions with their ressources
    array[1] = &c.a;        
    array[2] = &b.a;
    array[3] = &c.a;
    array[4] = &c.a;

    for (int i = 0; i < 5; i++)     //this usability i wanted to provide
    {
        (*(array[i]))();
    }

    getchar();
    return 0;
}

输出:

  

FooBar

     

FooBarFooBarBar

就我的例子来说,这是我可以按下来的。但我想这是不安全的代码。我偶然发现了可能的其他更简单的方法来实现这一点(std :: function和lambdas的其他用途(我可能试图在这里部分地重新发明))。

起初我曾尝试将“this”传递给function<void()>*AFunctionConstructor::constructFunction(CallerTypeFunc func)中的绑定函数 但是,我现在通过动态向上播放。 此外,AFunctionConstructor的功能首先应该在A的构造函数中实现。