【问题标题】:What is the proper way to reference a member function of a class?引用类的成员函数的正确方法是什么?
【发布时间】:2016-12-24 14:20:21
【问题描述】:
#include <iostream>
#include <algorithm>
#include <numeric>
#include <vector>
using namespace std;

class C
{
public:
    vector<int> CSort();
    bool Func(int x, int y);
private:
    vector<int> data;
};

vector<int> C::CSort()
{
    vector<int> result(data.size(), 0);
    iota(result.begin(), result.end(), 0);
    sort(result.begin(), result.end(), Func);
    return result;
}

bool C::Func(int x, int y)
{
    return (data[x] > data[y]);
}

在我上面定义的类C 中,我想使用成员函数Func 获得datastd::sort 的顺序向量。结果是一个错误

'C::Func':非标准语法;使用 '&' 创建指向成员的指针

我相信这与Why doesn't reference-to-member exist in C++有关。

但是,我想不出在std::sort 中引用此函数的正确方法。如何正确实施?

【问题讨论】:

  • @ArchbishopOfBanterbury 你是对的,初始化一个降序向量是一个很好的提醒,非常感谢 ;)
  • 附带说明,std::sort(result, &amp;C::Func); 应该与即将推出的 Ranges TS 一起开箱即用。

标签: c++ sorting std


【解决方案1】:

lambda 可以工作:

#include <iostream>
#include <algorithm>
#include <numeric>
#include <vector>
using namespace std;

class C
{
public:
    vector<int> CSort();
    bool Func(int x, int y);
private:
    vector<int> data;
};

vector<int> C::CSort()
{
    vector<int> result(data.size(), 0);
    iota(data.begin(), data.end(), 0);
    sort(data.begin(), data.end(), [this](auto& l, auto& r) {return Func(l, r); });
    return result;
}

bool C::Func(int x, int y)
{
    return (data[x] > data[y]);
}

int main()
{
    C c;
}

或绑定:

#include <iostream>
#include <algorithm>
#include <numeric>
#include <vector>
#include <functional>

using namespace std;

class C
{
public:
    vector<int> CSort();
    bool Func(int x, int y);
private:
    vector<int> data;
};

vector<int> C::CSort()
{
    vector<int> result(data.size(), 0);
    iota(data.begin(), data.end(), 0);
    sort(data.begin(), data.end(), std::bind(&C::Func,this,std::placeholders::_1,std::placeholders::_2));
    return result;
}

bool C::Func(int x, int y)
{
    return (data[x] > data[y]);
}

int main()
{
    C c;
}

【讨论】:

  • 在通过 std::mem_fn 获取函数之前,不要将 std::bind 用于成员函数,但老实说,在 C++14 中两者都是不必要的
  • @Mgetz 有趣。但这将如何运作?在这个例子中我们不需要绑定到一个特定的实例吗?
  • 我们可以,但是在 C++ 中获取成员函数引用的安全方法是使用std::mem_fn,这也是一种简单的方法。返回的函数对象保证将this参数作为第一个参数。而像您使用的指向成员的函数并不是 ABI 特定的实现细节。
  • 不,它既不是特别安全也不是特别容易。最好的方法就是使用 lambda。
  • @Mgetz 你的意思是像std::bind(std::mem_fn(&amp;C::Func),this,std::placeholders::_1,std::placeholders::_2))吗?
【解决方案2】:

你有几个选择:

如果您无法访问 C++11,您可以回到老学校并实现自己的保留状态的比较器:

class C
{
    friend struct MyComp;
public:
    vector<int> CSort();
private:
    vector<int> data;
};

struct MyComp
{
    C* data;
    MyComp(C* data) : data(data) {}
    bool operator()(int x, int y)
    {
        return data->data[x] > data->data[y];
    }
};

vector<int> C::CSort()
{
    vector<int> result(data.size(), 0);
    iota(data.begin(), data.end(), 0);
    sort(data.begin(), data.end(), MyComp(this));
    return result;
}

但是,如果你这样做,你可以只使用 lambda:

vector<int> C::CSort()
{
    vector<int> result(data.size(), 0);
    iota(data.begin(), data.end(), 0);
    sort(data.begin(), data.end(), [this] (int x, int y) {
        return (data[x] > data[y]);
    });
    return result;
}

【讨论】:

    【解决方案3】:

    快速而肮脏的方式:将Func移到课堂外。

    #include <iostream>
    #include <algorithm>
    #include <numeric>
    #include <vector>
    using namespace std;
    
    class C
    {
     public:
      vector<int> CSort();
     private:
      vector<int> data;
    };
    
    bool Func(int x, int y) {
      return x > y;
    }
    
    vector<int> C::CSort()
    {
      vector<int> result(data.size(), 0);
      // iota(data.begin(), data.end(), 0);
      sort(data.begin(), data.end(), Func);
      return result;
    }
    

    【讨论】:

    • 投反对票为什么? C++不允许引用非静态成员函数。
    • 它没有直接回答这个问题,但我认为它不值得一票。 (特别是没有一些解释)
    • @gongzhitaao 我相信我的代码有错误。很抱歉造成误会。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-16
    • 2014-05-05
    • 2015-03-09
    • 2018-12-31
    相关资源
    最近更新 更多