未定义引用与嵌套 class 模板静态常量成员
Undefined reference vs. nested class template static const member
我有这样的东西,它被其他 3 classes (list, queue, stack...) 继承:
template <typename generic>
class singlyLinkedList
{
protected:
class innerNode
{
public:
innerNode *NextNode;
generic Value;
innerNode( generic value, innerNode *next = NULL ) :
NextNode(next), Value(value) {}
};
innerNode *FirstNode;
innerNode *LastNode;
size_t CurrentSize;
public:
class iterator
{
private:
innerNode *InnerNode;
const bool IsDeepCopy;
static const innerNode DefaultNode;
public:
iterator( innerNode *node = NULL ) : InnerNode(node), IsDeepCopy(false)
{
if (node == NULL)
this->InnerNode = (innerNode*)(&(iterator::DefaultNode));
}
iterator( innerNode *node, bool deepCopy ) : IsDeepCopy(deepCopy)
{
if (deepCopy) this->InnerNode = new innerNode(node->Value, node->NextNode);
else this->InnerNode = node;
}
~iterator()
{
if (this->IsDeepCopy) delete this->InnerNode;
}
inline bool isNull() const
{
return (this->InnerNode != &(iterator::DefaultNode));
}
// ...other iterator members which doesn't use the static member
};
// ...other singlyLinkedList members, some returning iterators
};
我曾经有一个单独的 singlyLinkedNode class 作为节点和迭代器,使用友谊来提供对列表的特殊访问 classes...然后我决定我' d 将所有内容更改为现在的样子(如上一节所示)。
由于 iterator
嵌套在 class 模板中,据我所知,可以在 headers 中定义 class 模板的静态常量成员,我认为没有理由从该代码的链接器中得到 Undefined Reference 错误。但是,我得到这个:
/tmp/cc6vtGDj.o: In function `basicSinglyLinkedList<double>::iterator::iterator(basicSinglyLinkedList<double>::innerNode*)':
oo_test.cpp:(.text._ZN21basicSinglyLinkedListIdE8iteratorC2EPNS0_9innerNodeE[_ZN21basicSinglyLinkedListIdE8iteratorC5EPNS0_9innerNodeE]+0x2d): undefined reference to `basicSinglyLinkedList<double>::iterator::DefaultNode'
/tmp/cc6vtGDj.o: In function `basicBinarySearchTree<int>::iterator::iterator(basicBinarySearchTree<int>::innerNode*)':
oo_test.cpp:(.text._ZN21basicBinarySearchTreeIiE8iteratorC2EPNS0_9innerNodeE[_ZN21basicBinarySearchTreeIiE8iteratorC5EPNS0_9innerNodeE]+0x2a): undefined reference to `basicBinarySearchTree<int>::DefaultNode'
collect2: error: ld returned 1 exit status
Compilation failed.
有人可以解释一下为什么我会收到 singlyLinkedList<>::iterator::DefaultNode
的链接器错误或者...我必须设置什么替代方法 "default node" 来控制无效的迭代器以及它们指向的位置?
在header 中定义模板class 的静态const 成员完全没问题。但关键是你必须定义它——你只在这里声明它。
在class定义之外,您应该添加
template <typename T>
singlyLinkedList::innerNode singlyLinkedList::iterator::defaultNode = T();
(或类似的东西)来初始化存储,就像在常规 class 的静态成员的实现文件中一样。链接器将负责将所有模板化的静态变量合并到最终的可执行文件中,就像它对模板函数所做的那样。
编辑:
上面的内容超出了我的脑海:考虑得更多一些,定义需要更像
template <typename T>
const typename singlyLinkedList<T>::innerNode singlyLinkedList<T>::iterator::defaultNode = T{};
但我现在无法尝试。不过,编译器应该指导它真正想让你说什么。
我有这样的东西,它被其他 3 classes (list, queue, stack...) 继承:
template <typename generic>
class singlyLinkedList
{
protected:
class innerNode
{
public:
innerNode *NextNode;
generic Value;
innerNode( generic value, innerNode *next = NULL ) :
NextNode(next), Value(value) {}
};
innerNode *FirstNode;
innerNode *LastNode;
size_t CurrentSize;
public:
class iterator
{
private:
innerNode *InnerNode;
const bool IsDeepCopy;
static const innerNode DefaultNode;
public:
iterator( innerNode *node = NULL ) : InnerNode(node), IsDeepCopy(false)
{
if (node == NULL)
this->InnerNode = (innerNode*)(&(iterator::DefaultNode));
}
iterator( innerNode *node, bool deepCopy ) : IsDeepCopy(deepCopy)
{
if (deepCopy) this->InnerNode = new innerNode(node->Value, node->NextNode);
else this->InnerNode = node;
}
~iterator()
{
if (this->IsDeepCopy) delete this->InnerNode;
}
inline bool isNull() const
{
return (this->InnerNode != &(iterator::DefaultNode));
}
// ...other iterator members which doesn't use the static member
};
// ...other singlyLinkedList members, some returning iterators
};
我曾经有一个单独的 singlyLinkedNode class 作为节点和迭代器,使用友谊来提供对列表的特殊访问 classes...然后我决定我' d 将所有内容更改为现在的样子(如上一节所示)。
由于 iterator
嵌套在 class 模板中,据我所知,可以在 headers 中定义 class 模板的静态常量成员,我认为没有理由从该代码的链接器中得到 Undefined Reference 错误。但是,我得到这个:
/tmp/cc6vtGDj.o: In function `basicSinglyLinkedList<double>::iterator::iterator(basicSinglyLinkedList<double>::innerNode*)':
oo_test.cpp:(.text._ZN21basicSinglyLinkedListIdE8iteratorC2EPNS0_9innerNodeE[_ZN21basicSinglyLinkedListIdE8iteratorC5EPNS0_9innerNodeE]+0x2d): undefined reference to `basicSinglyLinkedList<double>::iterator::DefaultNode'
/tmp/cc6vtGDj.o: In function `basicBinarySearchTree<int>::iterator::iterator(basicBinarySearchTree<int>::innerNode*)':
oo_test.cpp:(.text._ZN21basicBinarySearchTreeIiE8iteratorC2EPNS0_9innerNodeE[_ZN21basicBinarySearchTreeIiE8iteratorC5EPNS0_9innerNodeE]+0x2a): undefined reference to `basicBinarySearchTree<int>::DefaultNode'
collect2: error: ld returned 1 exit status
Compilation failed.
有人可以解释一下为什么我会收到 singlyLinkedList<>::iterator::DefaultNode
的链接器错误或者...我必须设置什么替代方法 "default node" 来控制无效的迭代器以及它们指向的位置?
在header 中定义模板class 的静态const 成员完全没问题。但关键是你必须定义它——你只在这里声明它。
在class定义之外,您应该添加
template <typename T>
singlyLinkedList::innerNode singlyLinkedList::iterator::defaultNode = T();
(或类似的东西)来初始化存储,就像在常规 class 的静态成员的实现文件中一样。链接器将负责将所有模板化的静态变量合并到最终的可执行文件中,就像它对模板函数所做的那样。
编辑:
上面的内容超出了我的脑海:考虑得更多一些,定义需要更像
template <typename T>
const typename singlyLinkedList<T>::innerNode singlyLinkedList<T>::iterator::defaultNode = T{};
但我现在无法尝试。不过,编译器应该指导它真正想让你说什么。