c++ - 奇怪地重复出现的模板模式 - 不能创建超过 1 个派生类?
问题描述
我坚持使用这种模式,因为我创建的派生类中只有一个被实例化。用 g++ 和 MSVS 检查。具体来说,只有我定义的第一个派生类被创建。编译器不会发出任何类型的警告。下面提供了完整的代码。
#include <iostream>
static int nodes = 0;
class TreeNode {
private:
int m_id;
public:
TreeNode() :
m_id(++nodes)
{}
TreeNode(int id) :
m_id(id)
{
++nodes;
}
TreeNode* left;
TreeNode* right;
int getId() const {
return m_id;
}
};
template<typename T>
//typename std::enable_if<std::is_base_of<TreeParser, T>::value>::type
class TreeParser {
protected:
TreeParser() {
++parsers;
}
public:
static uint32_t parsers;
void preorderTraversal(TreeNode* node) {
if (node != nullptr) {
processNode(node);
preorderTraversal(node->left);
preorderTraversal(node->right);
}
}
virtual ~TreeParser() = default;
void processNode(TreeNode* node) { // 2, 3. the generic algorithm is customized by derived classes
static_cast<T*>(this)->processNode(node); // depending on the client's demand - the right function will be called
}
};
template<class T>
uint32_t TreeParser<T>::parsers = 0;
class SpecializedTreeParser1 : public TreeParser<SpecializedTreeParser1> // 1. is-a relationship
{
public:
explicit SpecializedTreeParser1() :
TreeParser()
{}
void processNode(TreeNode* node) {
std::cout << "Customized (derived - SpecializedTreeParser1) processNode(node) - "
"id=" << node->getId() << '\n';
}
};
class SpecializedTreeParser2 : public TreeParser<SpecializedTreeParser2> // 1. is-a relationship
{
public:
explicit SpecializedTreeParser2() :
TreeParser()
{}
void processNode(TreeNode* node) {
std::cout << "Customized (derived - SpecializedTreeParser2) processNode(node) - "
"id=" << node->getId() << '\n';
}
};
int main()
{
TreeNode root;
TreeNode leftChild;
TreeNode rightChild;
root.left = &leftChild;
root.right = &rightChild;
std::cout << "Root id: " << root.getId() << '\n';
std::cout << "Left child id: " << leftChild.getId() << '\n';
std::cout << "Right child id: " << rightChild.getId() << '\n';
SpecializedTreeParser1 _1;
_1.preorderTraversal(&root);
SpecializedTreeParser2 _2;
_2.preorderTraversal(&root);
}
输出是:
Root id: 1
Left child id: 2
Right child id: 3
Customized (derived - SpecializedTreeParser1) preorderTraversal() - id=1
Customized (derived - SpecializedTreeParser1) preorderTraversal() - id=2
Customized (derived - SpecializedTreeParser1) preorderTraversal() - id=1963060099 // what is that?
为什么我不能实例化第二个派生类?
解决方案
我没记错,你的程序有未定义的行为。and的left
andright
指针未初始化,因此一旦到达那里,您的程序就会崩溃。这也是为什么你最终会得到奇怪的原因:它正在从某个随机内存位置读取......</p>
leftChild
rightChild
preorderTraversal()
id
要解决此问题,请确保 a 的left
andright
成员TreeNode
始终初始化nullptr
为您的其余代码似乎期望的那样:
class TreeNode {
…
TreeNode* left = nullptr;
TreeNode* right = nullptr;
…
};
推荐阅读
- google-apps-script - 如何在执行后删除谷歌脚本ClockTrigger
- sql - 错误 42803。列 XXXX 必须显示子句 GROUP BY 或在聚合函数中使用
- node.js - 节点 cron 作业仅在 GCP App Engine 上第一次执行
- angular - 导入 Angular 子项目时出错
- javascript - 单击按钮后为所有连接的用户重新加载页面
- html - 我们可以用angular中的自定义css覆盖选择器的默认样式吗
- python - 从 Python 中的多个列中删除相同的元素
- python - 如何使用 selenium 读取 python 中的隐藏文本?
- c# - 如何在 Visual Studio 中解决“CA0001:运行代码分析时出现未知错误”
- asp.net-core - HttpContext.User 在 Asp.net 核心 MVC 3.1 中的控制器内为空