如何将仅被子类初始化成员的Map设为抽象类且无需子类实现虚方法
解决方案
方法1:用纯虚析构函数实现抽象类
C++允许将析构函数声明为纯虚函数,这样既能让Map成为抽象类(无法实例化),又不需要派生类显式重写它——编译器会自动为派生类生成析构函数,只要你给基类的纯虚析构提供定义即可。完美匹配你的需求:所有功能保留在Map中,子类只负责初始化邻接表。
示例代码:
#include <unordered_map> #include <vector> #include <iostream> class Map { protected: const std::unordered_map<std::string, std::vector<std::string>> adjacencyList; // 声明纯虚析构函数 virtual ~Map() = 0; public: // 所有通用功能都在这里实现 void printAdjacency() const { for (const auto& [city, neighbors] : adjacencyList) { std::cout << city << " 邻接城市:"; for (const std::string& n : neighbors) { std::cout << n << " "; } std::cout << "\n"; } } }; // 必须为纯虚析构提供定义,否则会出现链接错误 Map::~Map() {} class France : public Map { public: // 子类仅通过初始化列表传递邻接表 France() : Map({ {"巴黎", {"里昂", "马赛"}}, {"里昂", {"巴黎", "马赛"}} }) {} };
方法2:将基类构造函数设为protected
如果不需要Map是严格意义上的抽象类,只是想禁止外部实例化它,更简单的方式是把Map的构造函数设为protected。这样外部代码无法直接创建Map对象,但派生类可以正常继承并调用基类构造函数初始化邻接表。
示例代码:
#include <unordered_map> #include <vector> #include <iostream> class Map { protected: const std::unordered_map<std::string, std::vector<std::string>> adjacencyList; // 构造函数设为protected,禁止外部实例化 explicit Map(const std::unordered_map<std::string, std::vector<std::string>>& adj) : adjacencyList(adj) {} public: void printAdjacency() const { for (const auto& [city, neighbors] : adjacencyList) { std::cout << city << " 邻接城市:"; for (const std::string& n : neighbors) { std::cout << n << " "; } std::cout << "\n"; } } }; class Germany : public Map { public: Germany() : Map({ {"柏林", {"慕尼黑", "汉堡"}}, {"慕尼黑", {"柏林", "法兰克福"}} }) {} };
方案选择建议
- 如果你需要用
Map*或Map&的多态特性,优先选纯虚析构方案,它能保证Map是抽象类,符合多态场景的语义。 - 如果不需要多态,只是单纯禁止基类实例化,protected构造函数的方案更简洁,代码复杂度更低。
内容的提问来源于stack exchange,提问作者19172281
相关产品推荐
相关产品推荐

