2010-05-11 39 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()); 

請注意,這是而不是使用免費功能。爲了這種目的,通常優選仿函子。我還使用了一個名稱空間來顯示被排序的對象與排序對象的不同方式之間的關聯。你可能而不是他們的嵌套類,但我通常更喜歡公共命名空間(保持耦合儘可能寬鬆)。如果可以避免(在這種情況下,它可以),通過對象的公共接口,我會而不是訪問原始數據(甚至是隻讀訪問)。

相關問題