我的层次结构很少。我有以下内容:
RawSheet = vector<Country>
Country = vector<City>
City = vector<Building>
除了向量之外的类还包含一些其他有用的东西。问题是 我只能在整个结构中从上到下,即从RawSheet开始 我可以得到它的国家,然后每个国家我可以得到城市和每个城市 我可以得到它的建筑物。但我也需要能够做到这一点:给一座建筑,得到它的城市, 然后为纽约市获得其国家,最后获得该国家的RawSheet。是)我有的 现在基本上是一个上下连接的树,但不是从下到上。你能建议我的方法吗? 这样做,然后我如何管理这些链接?例如,每个城市都可以保留参考 一个国家,它自己的。其他人也一样......保留对父母的引用。
由于
答案 0 :(得分:1)
我会定义一个基类Layer
,它有一个指向父图层的指针和一个可以打印的名称。然后,您可以通过简单地继承此Layer
并使用新的C ++ 11继承构造函数来避免代码重复来定义层次结构中的所有层(在C ++ 98中,您必须在每个层中定义构造函数)具体层)。
我不会将子项存储在图层中,而是存储在std::multimap<Layer*, Layer*>
中,这样您就可以使用方便的成员函数equal_range
来获取应用程序中任何具体图层的所有子项(我称之为这个数据结构Atlas
)。
#include <map>
#include <string>
#include <utility>
#include <vector>
#include <iostream>
class Layer
{
public:
explicit Layer(std::string n, Layer* p = nullptr): name_(n), parent_(p) {}
std::string name() { return name_; }
Layer* parent() { return parent_; }
private:
std::string name_;
Layer* parent_;
};
// inheriting constructrors (C++11 only, retype constructors for C++98)
class City : public Layer { using Layer::Layer; };
class Country: public Layer { using Layer::Layer; };
class Planet : public Layer { using Layer::Layer; };
typedef std::multimap<Layer*, Layer*> Atlas;
int main()
{
Planet Earth("Earth");
Country USA("United States of America", &Earth);
Country FRA("France", &Earth);
std::vector<City> USA_cities = { City("Los Angeles", &USA), City("New York", &USA) };
std::vector<City> FRA_cities = { City("Bordeaux", &FRA), City("Paris", &FRA) };
Atlas a;
a.insert(std::make_pair(&Earth, &USA));
a.insert(std::make_pair(&Earth, &FRA));
for (auto& city: USA_cities)
a.insert(std::make_pair(&USA, &city));
for (auto& city: FRA_cities)
a.insert(std::make_pair(&FRA, &city));
auto countries = a.equal_range(&Earth);
std::cout << "Countries on planet " << countries.first->first->name() << " :\n";
for (auto it = countries.first; it != countries.second; ++it) {
auto country = it->second;
std::cout << country->name() << " (located on planet " << country->parent()->name() << "), with cities:\n";
auto cities = a.equal_range(country);
for (auto jt = cities.first; jt != cities.second; ++jt) {
auto city = jt->second;
std::cout << " " << city->name() << " (located in country " << city->parent()->name() << ")\n";
}
std::cout << "\n";
}
}
Live Example,输出如下:
Countries on planet Earth :
United States of America (located on planet Earth), with cities:
Los Angeles (located in country United States of America)
New York (located in country United States of America)
France (located on planet Earth), with cities:
Bordeaux (located in country France)
Paris (located in country France)
如您所见,您可以在此层次结构中上下迭代。
你可以在几个方面批评这个解决方案。类层次结构没有强制执行:Planet
可以有Cities
列表而没有中间Country
层等。您可以通过编译时检查或运行时强制执行此类操作类型信息。这是灵活性和安全性之间的权衡。
基类virtual
中也没有Layer
析构函数。只要您不尝试通过Layer*
删除任何具体的图层对象,就没有问题。也没有智能指针,因为所有Layer*
都是非拥有指针。如果您想要移动或复制建筑物(有时会发生),您可以轻松扩展它。
答案 1 :(得分:0)
这个问题有几种方法。我只露出一个。
您可以使用对容器的引用来封装容器的每个元素。类似的东西:
class Country;
class City {
public:
City(Country& c): country(c) {
}
private:
string name;
size_t population;
Country& country;
};
class Country {
string name;
vector<City> cities;
};
当然,您可以使用指针代替对容器的引用。但是,如果您想强制每个城市仅由一个国家拥有,请使用参考。在这种情况下,您必须为City类提供构造函数,如示例中所示。
将此示例扩展到层次结构的其他级别也很容易。