2013-07-08 54 views
2

我想知道如何實現以下設計。我沒有努力遵循標準慣例,以便將此虛擬代碼降到最低(例如,包括警衛)。爲了參數,我使用C++ 03,並且只使用標準庫組件。編譯C++多對多關係

TL; DR:在我的RestaurantRecipe類之間存在循環依賴關係。我有std::set<>一個指針RecipeRestaurant類的對象,反之亦然。我不能在另一箇中使用#include,但由於前向聲明,編譯器不允許我爲這些集合聲明一個自定義比較器,因爲value_type在這一點上仍然是不完整的類型。有沒有辦法做到這一點?

我已經在代碼中加入了註釋,這些代碼更詳細地解釋了我的問題。

/* 
* restaurant.h 
*/ 
#include <string> 
#include <set> 
/* 
* I cannot do this as recipe.h would need to include 
* restaurant.h, which restricts 
* me when I want to write a custom comparator. 
*/ 
// #include "recipe.h" 

class Recipe; 

// I know this will not work as Recipe has not yet been declared. 
struct RecipeComparator { 
    bool operator() (const Recipe* lhs, const Recipe* rhs) { 
     return lhs->price() < rhs->price(); 
    } 
}; 

class Restaurant { 
    public: 
     Restaurant(const std::string& name, float averagePrice); 
     float averagePrice() { return m_averagePrice; } 

    private: 
     std::string m_name; 
     float m_averagePrice; 
     /* 
     * I want to have the recipies sorted by their prices. 
     * I cannot define RecipeComparator here as Restaurant 
     * is an incomplete type till now. 
     */ 
     std::set< Recipe*, RecipeComparator > m_recipiesSorted; 

     /* 
     * This works, but does not do what I want. 
     */ 
     std::set< Recipe* > m_recipies; 
}; 

/* 
* recipe.h 
*/ 
#include <string> 
#include <set> 
/* 
* I cannot do this as restaurant.h would need to include 
* recipe.h, so I need to forward declare, which restricts 
* me when I want to write a custom comparator. 
*/ 
// #include "restaurant.h" 

class Restaurant; 

// I know this will not work as Restaurant has not yet been declared. 
struct RestaurantComparator { 
    bool operator() (const Restaurant* lhs, const Restaurant* rhs) { 
     return lhs->averagePrice() < rhs->averagePrice(); 
    } 
}; 

class Recipe { 
    public: 
     Recipe(const std::string& name, float price); 
     float price() { return m_price; } 

    private: 
     std::string m_name; 
     float m_price; 
     /* 
     * This is what I want as I want to have the restaurants sorted 
     * by their average prices. 
     * I cannot define RestaurantComparator here as Restaurant 
     * is an incomplete type till now. 
     */ 
     std::set< Restaurant*, RestaurantComparator > m_restaurantsSorted; 

     /* 
     * This works, but does not do what I want. 
     */ 
     std::set< Restaurant* > m_restaurants; 

}; 
+0

移動的布爾'運營商()(常量餐廳*,const的餐廳。*)的定義'到cpp文件,並保持在聲明的標題。 –

+0

將默認值設置爲訂單的小於運算符...難道你不能只爲兩個類實現它,而不是定義顯式比較器嗎? –

+0

@StefanHaustein不確定OP能做到這一點。他的代碼中的std :: set <> :: key_type'是指針,你不能重載'operator <'把2個指針類型作爲參數。 – greatwolf

回答

4

一個想法是你比較定義移動到一個.cpp源,同時保持了這些聲明在標題中。這樣,restaurant.hrecipe.h仍然只能通過名稱相互引用,所以前向聲明仍然足夠。

// restaurant_recipe_comparators.h 
// probably too long, give it a better name 
struct RestaurantComparator 
{ 
    bool operator() (const Restaurant *, const Restaurant *); 
}; 

struct RecipeComparator 
{ 
    bool operator() (const Recipe *, const Recipe *); 
}; 

// restaurant_recipe_comparators.cpp 
bool RestaurantComparator::operator() (const Restaurant* lhs, const Restaurant* rhs) 
{ 
    return lhs->averagePrice() < rhs->averagePrice(); 
} 


bool RecipeComparator::operator() (const Recipe* lhs, const Recipe* rhs) 
{ 
    return lhs->price() < rhs->price(); 
} 
+0

這工作!偉大的:-) – vvnraman