2013-09-30 4 views
3

У меня есть класс под названием «UltrasoundTemplate». Эти объекты UltrasoundTemplate содержат параметр int, который показывает, когда они определены (что-то вроде отметки времени). И у меня есть класс под названием «UltrasoundTarget», который содержит вектор UltrasoundTemplate. Я добавляю UltrasoundTemplates к вектору с push_back (ultrasoundTemplate).Сортировка вектора класса

Теперь я хочу отсортировать вектор по заказу штампов времени вместо заказа, который я добавил в вектор.

Я нашел много ответов в google, которые показывают мне одно и то же решение, но, очевидно, я все еще делаю что-то неправильно. Вот фрагменты кода, я думаю, необходимо найти решение:

ultrasoundTemplate.h

class UltrasoundTemplate 
{ 
public: 
UltrasoundTemplate(/*...*/); 
int getVolumePos() { return volume_; } 
private: 
int volume_; 
}; 

ultrasoundTarget.h

//the sort algorithm 
struct MyTemplateSort { 
bool operator() (UltrasoundTemplate t1, UltrasoundTemplate t2){ 
    int it1 = t1.getVolumePos(); 
    int it2 = t2.getVolumePos(); 

    if (it1 < it2) 
     return true; 
    return false; 
} 
}; 

class UltrasoundTarget 
{ 
public: 
UltrasoundTarget(/*...*/); 
vector<UltrasoundTemplate> getTemplates() { return USTemplateVector_; } 
private: 
vector<UltrasoundTemplate> USTemplateVector_; 
}; 

FMainWindow.cpp

void FMainWindow::match_slot() 
{ 
int i; 
//here I get the name of the target I'm looking for 
QTreeWidgetItem *item = targetInfoWidget_->treeWidget->currentItem(); 
int index = targetInfoWidget_->treeWidget->indexOfTopLevelItem(item); 
QString itemToAppendName = item->text(0); 
for(i = 0; i < USTargetVector.size(); i++){ 
    if(USTargetVector.at(i).getName() == itemToAppendName) { 
    //here I try to sort 
    MyTemplateSort tmpltSrt; 
    std::sort(USTargetVector.at(i).getTemplates().begin(), 
       USTargetVector.at(i).getTemplates().end(), tmpltSrt);  
    break; 
    } 
} 

качестве Пример: я определяю Template1 в Volume (0), Template2 в Volume (70) и Template3 в Volume (40). Теперь заказ (Template1, Template2, Template3), но я хочу, чтобы он был (Template1, Template3, Template2). Но этот код этого не делает.

Если нет информации, просто скажите мне, и я предоставлю больше кода.

Спасибо большое.

+0

Вы забыли назначить 'volume_', возможно? – Katniss

ответ

5

Вашего getTemplates() метод возвращает по стоимости, что делает беспорядок здесь:

std::sort(USTargetVector.at(i).getTemplates().begin(), 
      USTargetVector.at(i).getTemplates().end(), tmpltSrt);  

Вы разбираете несовместимый диапазон итератора. Вы можете решить эту конкретную проблему, возвращая ссылку:

vector<UltrasoundTemplate>& getTemplates() { return USTemplateVector_; } 

Это обычная практика, чтобы добавить перегрузку const к такому способу:

const vector<UltrasoundTemplate>& getTemplates() const { return USTemplateVector_; } 

Вы также можете изменить свой функтор сравнения, чтобы избежать ненужных копий (и для общего удобства чтения и сопзЬ корректности):

struct MyTemplateSort { 
    bool operator() const (const UltrasoundTemplate& t1, const UltrasoundTemplate& t2) 
    { 
    return t1.getVolumePos() < t2.getVolumePos(); 
    } 
}; 

Это потребует, что вы делаете getVolumePos() с const метод, которым он должен быть в любом случае:

class UltrasoundTemplate 
{ 
public: 
... 
int getVolumePos() const { return volume_; } 
... 
}; 

Обратите внимание, что это не правило, хорошая практика, чтобы предоставить ссылки на приватных данных класса. Если возможно, вы должны найти способ удалить это из интерфейса UltraSoundTarget. Например, вы можете открыть пару итераторов и/или дать классу метод сортировки.

+0

Я думаю, что вы затронули слишком много тем в одном ответе! Если он намеревается изменить содержимое UltrasoundTarget, ему не следует использовать const & версию getTemplates, потому что содержимое ссылки const не может измениться. –

+0

Да, я вижу это. +1 к ответу, кстати. Хорошая запись. – WhozCraig

+0

@IanMedeiros Они не будут использовать перегрузку 'const', но хорошо иметь один для случаев, когда это необходимо. – juanchopanza

0

ответ juanchopanza правильный, проблема в том, как вы возвращаете вектор из UltrasoundTarget. Чтобы затронуть другую тему, возможно, было бы неплохо немного изменить дизайн вашей реализации. Поскольку UltrasoundTarget является контейнером Ultrasound's, имеет смысл реализовать сортировку как метод этого класса, таким образом, вы имеете прямой доступ к USTemplateVector_ и сохраните ненужные копии.Что-то вроде:

class UltrasoundTarget 
{ 
public: 
UltrasoundTarget(/*...*/); 
vector<UltrasoundTemplate> getTemplates() { return USTemplateVector_; } 

void sort(); 

private: 
vector<UltrasoundTemplate> USTemplateVector_; 
}; 

void UltrasoundTarget::sort() 
{ 
std::sort(USTemplateVector_.begin(), USTemplateVector_.end(), tmpltSrt); 
} 

void FMainWindow::match_slot() 
{ 
int i; 
//here I get the name of the target I'm looking for 
QTreeWidgetItem *item = targetInfoWidget_->treeWidget->currentItem(); 
int index = targetInfoWidget_->treeWidget->indexOfTopLevelItem(item); 
QString itemToAppendName = item->text(0); 
for(i = 0; i < USTargetVector.size(); i++){ 
if(USTargetVector.at(i).getName() == itemToAppendName) 
{ 
    //here I try to sort 
    MyTemplateSort tmpltSrt; 
    USTargetVector.at(i).sort(); 
    break; 
} 
} 
Смежные вопросы