我会定义一个基类Layer
,它有一个指向父层的指针和一个可以打印的名称。然后,您可以通过简单地从 this 继承Layer
并使用新的 C++11 继承构造函数功能来定义层次结构中的所有层,以避免代码重复(在 C++98 中,您必须在每个具体层中定义构造函数)。
我不会将子层存储在层中,而是存储在 a 中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";
}
}
具有以下输出的实时示例:
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)
如您所见,您可以向上和向下迭代此层次结构。
您可以在几个方面批评此解决方案。类层次结构没有强制执行:aPlanet
可以有一个Cities
没有中间Country
层的列表,等等。您可以通过编译时检查或运行时类型信息来强制执行这些操作。这是灵活性和安全性之间的权衡。
virtual
基类中也没有析构函数Layer
。只要您不尝试通过 删除任何具体的图层对象Layer*
,就没有问题。也没有智能指针,因为它们Layer*
都是非拥有指针。如果您想移动或复制建筑物(有时会发生),您可以轻松扩展它。