【发布时间】:2021-11-21 12:42:02
【问题描述】:
我知道我想要什么,但我不知道如何告诉编译器我想要什么。我在 .h 和 .cpp 文件中拆分了声明和方法定义,但是 .cpp 文件包含在标头中,所以我所做的只是单独的声明和定义。
头文件 (avltree.h) - 它包含源文件!:
template < class KEY_T, class DATA_T >
class CAvlTree {
public:
//----------------------------------------
template < class KEY_T, class DATA_T >
class CNode;
typedef CNode< KEY_T, DATA_T> * tNodePtr;
template < class KEY_T, class DATA_T >
class CNode {
public:
KEY_T key;
DATA_T data;
CNode< KEY_T, DATA_T > * left;
CNode< KEY_T, DATA_T > * right;
char balance;
CNode() : left(nullptr), right(nullptr), balance(0) {}
CNode(KEY_T key, DATA_T data) :
key (key), data (data), left(nullptr), right(nullptr), balance(0) {}
};
//----------------------------------------
template < class KEY_T, class DATA_T >
struct tAvlInfo {
CNode< KEY_T, DATA_T> * root;
CNode< KEY_T, DATA_T> * current;
KEY_T key;
bool isDuplicate;
bool branchChanged;
};
typedef bool (* tNodeProcessor) (CNode< KEY_T, DATA_T> * nodePtr);
private:
tAvlInfo< KEY_T, DATA_T > m_info;
//----------------------------------------
public:
DATA_T* Find(KEY_T& key);
private:
CNode< KEY_T, DATA_T> * AllocNode(void);
};
#include "avltree.cpp"
源文件(avltree.cpp):
template < typename KEY_T, typename DATA_T >
DATA_T* CAvlTree< KEY_T, DATA_T >::Find (KEY_T& key)
E0276 name followed by '::' must be a class or namespace name
{
CNode* root;
for (CNode* node = m_info.root; node; ) {
if (key < node->key)
node = node->left;
else if (key > root->key)
node = node->right;
else {
m_info.current = node;
return &node->data;
}
}
return nullptr;
}
template < typename KEY_T, typename DATA_T >
CNode* CAvlTree< KEY_T, DATA_T >::AllocNode (void)
E0020 identifier "CNode" is undefined
E0864 CAvlTree is not a template
{
if (m_info.current = new CNode < KEY_T, DATA_T >) {
m_info.branchChanged = true;
return m_info.current;
}
return nullptr;
}
编译器所说的(VS 2019 社区,启用了 c++2020):
E0276 name followed by '::' must be a class or namespace name
E0020 identifier "CNode" is undefined
E0864 CAvlTree is not a template
我完全不知道如何以正确的方式写下来。请赐教。
对于具有单个类型名的模板类,我有类似的代码,它可以工作,但无法从中得出如何为两个类型名执行此操作的结论。
在我的源代码中使用 tNodePtr 类型而不是 CNode * 也不起作用。
顺便说一句,我知道编译器不会仅仅因为我使用相同的名称而从 CAvlTree 声明中“传输”KEY_T 和 DATA_T。
【问题讨论】:
-
source file (avltree.cpp):模板可疑,见why-can-templates-only-be-implemented-in-the-header-file -
[Tangent] 你真的不应该把你的模板定义文件称为 cpp 文件。 cpp 文件需要编译,而你的不是。我称它为 tpp 或 ipp 文件来区分它。
-
只是一个建议 - 不要调用实现文件 *.cpp - IDE/构建系统将尝试编译它们 - 它称之为 *.imp 或 *.inl 或类似的东西。
-
编译器应该如何知道为
CNode(在CNode* root;和函数定义中的其他地方)选择哪些模板参数?您认为template < class KEY_T, class DATA_T > class CNode;中的KEY_T和DATA_T应该是什么? -
@t.niese 我也同意并重新打开了 Q。
标签: c++ template-classes