2010-05-11 38 views
3

在类中,我试图通过传递相同类的方法来排序向量。但它在编译时会出错。任何人都可以告诉问题是什么?谢谢!传递类方法而不是std :: sort中的函数

它提供了以下错误: 参数bool (Sorter::)(D&, D&)' does not match bool类型(分拣机:: *)(d &,d &)”

我一直在使用sortBynumber(D const& d1, D const& d2)

#include<vector> 
#include<stdio.h> 
#include<iostream> 
#include<algorithm> 

class D { 
     public:     
      int getNumber();    
      D(int val); 
      ~D(){}; 
     private: 
       int num; 
}; 

D::D(int val){ 
     num = val; 
     }; 

int D::getNumber(){ 
    return num; 
}; 


class Sorter { 
     public:     
      void doSorting(); 
      bool sortByNumber(D& d1, D& d2); 
      std::vector<D> vec_D;   
      Sorter(); 
      ~Sorter(){}; 
     private: 
       int num; 
}; 

Sorter::Sorter(){     
     int i; 
     for (i = 0; i < 10; i++){ 
      vec_D.push_back(D(i)); 
      } 
     }; 

bool Sorter::sortByNumber(D& d1, D& d2){ 
    return d1.getNumber() < d2.getNumber(); 
    }; 

void Sorter::doSorting(){ 
    std::sort(vec_D.begin(), vec_D.end(), this->sortByNumber); 
    }; 




int main(){  
    Sorter s; 
    s.doSorting(); 

    std::cout << "\nPress RETURN to continue..."; 
    std::cin.get(); 

    return 0; 
} 
+1

你为什么要'sortByNumber'作为成员函数?它也可以是一个免费的功能。 – Naveen 2010-05-11 05:16:01

+0

你不必明确说明'D'的析构函数。编译器可以免费获得完全相同的代码。更少的代码,更少的错误。 ;)另外,我看到'Sorter :: vector'是公开的。只是一个观察;这可能不是你想要的。另一件事:如果你知道向量的大小,那么你可以在'Sorter'的初始化列表中指定它,以避免重新分配。其他人已经谈到了const-correctness的重要性,所以你应该注意这一点。最后一件事情是:在for循环中,你应该有'i'作为循环的局部变量。 – wilhelmtell 2010-05-11 06:02:07

回答

5

Sorter::sortByNumber静也尝试。由于它不引用任何对象成员,因此不需要改变其他任何东西。

class Sorter { 
public:     
    static bool sortByNumber(const D& d1, const D& d2); 
    ... 
}; 

// Note out-of-class definition does not repeat static 
bool Sorter::sortByNumber(const D& d1, const D& d2) 
{ 
    ... 
} 

您还应该使用const的引用作为sortByNumber不应该被修改的对象。

+0

嗯,我试过这个,但现在它给出了以下错误:'不能声明成员函数'静态布尔Sorter :: sortByNumber(D&,D&)'有静态链接' – memC 2010-05-11 05:20:51

+0

@memC - 不要使用'static'定义本身。在'class'里面声明之前只使用'static'。 – 2010-05-11 05:25:43

+0

@Samuel:感谢您的更新!我早些时候宣布不合格的定义是静态的。所以做了这个改变。但是,将'D&'改为'const D&'会给出以下错误:'将'const D'作为'int D :: getNumber()'的'this'参数传递'丢弃限定符' – memC 2010-05-11 05:25:54

1

我认为没有任何理由使sortByNumber成为类Sorter的成员函数。如果你使它成为一个自由函数,你可以更容易地进行排序,以避免所有难看的绑定代码。此外,您应该在代码中适用的任何地方使用const。下面是使用免费的功能,这样做的例子:

首先更改int getNumber()为const功能int getNumber() const;

然后写你的免费功能sortByNumber通过const引用再次服用参数。 bool sortByNumber(const D& d1, const D& d2);

你可以叫sort为: std::sort(vec_D.begin(), vec_D.end(), sortByNumber);

+0

嗨Naveen,这个排序只在这个类中完成。所以我认为最好是把它放在类内而不是一个自由函数。但是似乎将它作为一个类函数会有相当多的开销。 – memC 2010-05-11 05:39:40

+1

@memC这不是你如何决定函数是否应该是成员。当你成为一名会员时,你基本上可以提升自己的权利:你可以让它访问班级的所有受保护和私人会员。所以班级成员不是“与班级相关的东西”,而是“需要进入班级内部的东西”。如果这个类需要一些特殊的服务,那么你可以创建一个静态链接的免费函数。也就是说,该函数将本地链接到类的编译单元。您可以通过将自由函数放入一个未命名的名称空间中来实现这一点。 – wilhelmtell 2010-05-11 05:54:54

2

我认为没有理由对sortByNumber()是一个成员函数。当它是一个成员函数时,它可以访问它不需要的东西(因此不应该有权访问)。提取方法并将其重构为函数对象:

struct sortByNumber { 
    bool operator()(const D& d1, const D& d2) const { 
     return d1.getNumber() < d2.getNumber(); 
    } 
}; 

或使其成为一个自由函数。鉴于选择,你应该更喜欢一个函数对象,因为如果它选择的话,编译器就可以嵌入代码。然后,您可以进行排序,像这样:

std::sort(vec_D.begin(), vec_D.end(), sortByNumber()); 

这就是说,你可以编译代码是像这样,与boost::bind()

std::sort(vec_D.begin(), vec_D.end(), 
      boost::bind(&Sorter::sortByNumber, this, _1, _2)); 

您需要Boost库为工作,你将需要#include <boost/bind.hpp>

+0

Re:'bind1st' - 你应该尝试编译这些东西。首先,对于有两个参数的方法没有'mem_fun'。 (但是你可以用更先进的'std :: tr1 :: bind'编译东西。) – UncleBens 2010-05-11 06:44:00

+0

@UncleBens:s哦急!感谢您指出了这一点。是的,我应该更频繁地咨询我的编译器,让我的过度自信不时地休息一下。 – wilhelmtell 2010-05-11 07:12:25

3

除非你有一个很好的理由不这样做,只是定义为operator<你整理项目的类型,并用它做:

class D { 
    int val; 
public: 
    D(int init) : val(init) {} 
    bool operator<(D const &other) { return val < other.val; } 
}; 

class sorter { 
    std::vector<D> vec_D; 
public: 
    void doSorting() { std::sort(vec_d.begin(), vec_D.end()); } 
}; 

的方式你写你的sorter类取决于知道关于D类的内部的,以至于它们实际上是单个类(例如,如果没有其他类,它们看起来都不能做很多事情)。

根据猜测,您的sorter可能是您的真实代码的一些简化版本。该SortByNumber使得它听起来像原来的代码可能会支持许多不同类型的按键,类似的:

class D { 
    std::string name; 
    int height; 
    int weight; 
// ... 
}; 

,你会希望能够D对象的名字,身高或体重排序。在这样的情况下,比较是真的还涉及到D类,所以我可能会把它们放在一个公共的命名空间:

namespace D { 
class D { 
    std::string name; 
    int height; 
    int weight; 
public: 
    friend class byWeight; 
    friend class byHeight; 
    friend class byName; 
    // ... 
}; 

struct byWeight { 
    bool operator()(D const &a, D const &b) { 
     return a.weight < b.weight; 
    } 
}; 

struct byHeight { 
    bool operator()(D const &a, D const &b) { 
     return a.height < b.height; 
    } 
}; 

struct byName { 
    bool operator()(D const &a, D const &b) { 
     return a.name < b.name; 
    } 
}; 
} 

然后排序会看起来像:

std::vector<D::D> vec_D; 

// sort by height: 
std::sort(vec_D.begin(), vec_D.end(), D::byHeight()); 

// sort by weight: 
std::sort(vec_D.begin(), vec_D.end(), D::byWeight()); 

// sort by name: 
std::sort(vec_D.begin(), vec_D.end(), D::byName()); 

请注意,这是而不是使用免费功能。为了这种目的,通常优选仿函子。我还使用了一个名称空间来显示被排序的对象与排序对象的不同方式之间的关联。你可能而不是他们的嵌套类,但我通常更喜欢公共命名空间(保持耦合尽可能宽松)。如果可以避免(在这种情况下,它可以),通过对象的公共接口,我会而不是访问原始数据(甚至是只读访问)。

相关问题