鱼C论坛

 找回密码
 立即注册
查看: 1445|回复: 7

[已解决]C++中关于模板类定义失败的问题

[复制链接]
发表于 2021-3-11 15:21:21 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
问题:我已经在.cpp文件中对声明进行了定义,但是却报错undefined reference to `BTnode<int>::BTnode(int const&)'| ,这是为什么

代码如下:

头文件:
//.h文件中,对二叉树结点类声明

#ifndef BTNODE_H_INCLUDED
#define BTNODE_H_INCLUDED

template <typename valType>
class BTnode
{
public:
    //...
    BTnode(const valType &val);
    //...
private:
   valType _val;
   int _cnt;
   BTnode* _lchild;
   BTnode* _rchild;
};

#endif


源文件:
//.cpp文件中对BTnode(const valType &val) 进行定义
#include “BTnode.h”  

template <typename valType>
inline BTnode<valType>::
    BTnode(const valType &val):_val(val)
    {
        _cnt=1;
        _lchild=_rchild=0;
    }

main函数:
#include <iostream>
#include "BinaryTree.h"
#include "BTnode.h"
#include <string.h>

using namespace std;

int main()
{
    BTnode<int> bt(3);
    return 0;
}

程序报错:
undefined reference to `BTnode<int>::BTnode(int const&)'|

问题:我已经在.cpp文件中对声明进行了定义,但是却报错undefined reference to `BTnode<int>::BTnode(int const&)'| ,这是为什么?
最佳答案
2021-3-11 16:08:05
547658697 发表于 2021-3-11 15:57
BTnode模板实例化出现了问题,问题应该就在BTnode.cpp当中,因为我尝试直接在BTnode.h上,在类内部定义, ...

对,没错
模板的声明和定义不能分开,把 BTnode.cpp 的内容合并到 BTnode.h 就可以了
  1. #ifndef BTNODE_H_INCLUDED
  2. #define BTNODE_H_INCLUDED

  3. template <typename Type>
  4. class BinaryTree;

  5. template <typename valType>
  6. class BTnode
  7. {
  8. public:
  9.     friend class BinaryTree<valType>;
  10.     BTnode(const valType &val);
  11.     void insert_value( const valType &val);
  12.     void lchild_leaf(BTnode<valType> *leaf,BTnode<valType> *subtree );
  13.     void remove_value(valType &val , BTnode<valType> *prev);
  14. private:
  15.    valType _val;
  16.    int _cnt;
  17.    BTnode* _lchild;
  18.    BTnode* _rchild;
  19. };

  20. template <typename valType>
  21. inline BTnode<valType>::
  22.     BTnode(const valType &val):_val(val)
  23.     {
  24.         _cnt=1;
  25.         _lchild=_rchild=0;
  26.     }


  27. template <typename valType>
  28. inline void BTnode<valType>::
  29.     insert_value ( const valType &val )
  30.     {
  31.         if(_val == val )
  32.             _cnt++;
  33.         if(_val < val)
  34.         {
  35.             if(! _lchild)
  36.                 _lchild = new BTnode<valType>(val);
  37.             else
  38.                 _lchild->insert_value(val);
  39.         }
  40.         if(_val > val)
  41.         {
  42.             if(! _rchild)
  43.                 _rchild = new BTnode<valType>(val);
  44.             else
  45.                 _rchild->insert_value(val);
  46.         }
  47.     }

  48. template <typename valType>
  49. inline void BTnode<valType>::
  50.     lchild_leaf(BTnode<valType> *leaf,BTnode<valType> *subtree )
  51.     {
  52.         //找到没有左孩子的结点
  53.         while (! subtree->_lchild )
  54.             subtree = subtree->_lchild;
  55.         //找到了 subtree所指结点没有左子树
  56.         subtree->_lchild = leaf;
  57.     }

  58. template <typename valType>
  59. inline void BTnode<valType>::
  60.     remove_value(valType &val , BTnode<valType> *prev)
  61.     {
  62.         if (val < _val)
  63.         {
  64.             if( !_lchild )
  65.                 return ;
  66.             else
  67.             {
  68.                 _lchild->remove_value(val,_lchild);
  69.             }
  70.         }
  71.         else
  72.         if (val > _val)
  73.         {
  74.             if( !_rchild )
  75.                 return ;
  76.             else
  77.             {
  78.                 _rchild->remove_value(val,_rchild);
  79.             }
  80.         }
  81.         else
  82.         {
  83.             if(_rchild)
  84.             {
  85.                 prev = _rchild;
  86.                 if(_lchild)
  87.                 {
  88.                     if(!prev -> _lchild )
  89.                         prev->_lchild =_lchild;
  90.                     else
  91.                         BTnode<valType>::lchild_leaf(_lchild,prev->_lchild);
  92.                 }
  93.             }
  94.             else
  95.                 prev = _lchild;
  96.             delete this;

  97.         }
  98.     }

  99. #endif // BTNODE_H_INCLUDED
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2021-3-11 15:37:00 | 显示全部楼层

回帖奖励 +1 鱼币

有个问题,这个是BinaryTree.h 文件的内容?
  1. 源文件:
  2. //.cpp文件中对BTnode(const valType &val) 进行定义
  3. #include “BTnode.h”  

  4. template <typename valType>
  5. inline BTnode<valType>::
  6.     BTnode(const valType &val):_val(val)
  7.     {
  8.         _cnt=1;
  9.         _lchild=_rchild=0;
  10.     }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-3-11 15:40:12 | 显示全部楼层
人造人 发表于 2021-3-11 15:37
有个问题,这个是BinaryTree.h 文件的内容?

这个是我.BTnode.cpp文件的内容,用来对BTnode.h当中的所有类声明进行定义,在这里我只截取了一部分。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-3-11 15:44:10 | 显示全部楼层
547658697 发表于 2021-3-11 15:40
这个是我.BTnode.cpp文件的内容,用来对BTnode.h当中的所有类声明进行定义,在这里我只截取了一部分。

把所有的源代码都贴出来,说明哪一个代码在哪一个源文件,我在这边帮你看看
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-3-11 15:55:32 | 显示全部楼层
人造人 发表于 2021-3-11 15:44
把所有的源代码都贴出来,说明哪一个代码在哪一个源文件,我在这边帮你看看

感谢!下面是我所有的代码,每个开头都标有文件名字,现在是测试BTnode模板实例化就出现了问题。

main.cpp
  1. #include <iostream>
  2. #include "BinaryTree.h"
  3. #include "BTnode.h"
  4. #include <string.h>

  5. using namespace std;

  6. template <typename elemType>
  7. ostream& operator << (ostream &os, BinaryTree<elemType> &bt)
  8. {
  9.     return bt.print(os);
  10. }

  11. int main()
  12. {
  13.     BTnode<int> bt(3);
  14.     return 0;
  15. }
复制代码


BTnode.h
  1. #ifndef BTNODE_H_INCLUDED
  2. #define BTNODE_H_INCLUDED

  3. template <typename Type>
  4. class BinaryTree;

  5. template <typename valType>
  6. class BTnode
  7. {
  8. public:
  9.     friend class BinaryTree<valType>;
  10.     BTnode(const valType &val);
  11.     void insert_value( const valType &val);
  12.     void lchild_leaf(BTnode<valType> *leaf,BTnode<valType> *subtree );
  13.     void remove_value(valType &val , BTnode<valType> *prev);
  14. private:
  15.    valType _val;
  16.    int _cnt;
  17.    BTnode* _lchild;
  18.    BTnode* _rchild;
  19. };

  20. #endif // BTNODE_H_INCLUDED
复制代码



BTnode.cpp
  1. #include "BTnode.h"


  2. template <typename valType>
  3. inline BTnode<valType>::
  4.     BTnode(const valType &val):_val(val)
  5.     {
  6.         _cnt=1;
  7.         _lchild=_rchild=0;
  8.     }


  9. template <typename valType>
  10. inline void BTnode<valType>::
  11.     insert_value ( const valType &val )
  12.     {
  13.         if(_val == val )
  14.             _cnt++;
  15.         if(_val < val)
  16.         {
  17.             if(! _lchild)
  18.                 _lchild = new BTnode<valType>(val);
  19.             else
  20.                 _lchild->insert_value(val);
  21.         }
  22.         if(_val > val)
  23.         {
  24.             if(! _rchild)
  25.                 _rchild = new BTnode<valType>(val);
  26.             else
  27.                 _rchild->insert_value(val);
  28.         }
  29.     }

  30. template <typename valType>
  31. inline void BTnode<valType>::
  32.     lchild_leaf(BTnode<valType> *leaf,BTnode<valType> *subtree )
  33.     {
  34.         //找到没有左孩子的结点
  35.         while (! subtree->_lchild )
  36.             subtree = subtree->_lchild;
  37.         //找到了 subtree所指结点没有左子树
  38.         subtree->_lchild = leaf;
  39.     }

  40. template <typename valType>
  41. inline void BTnode<valType>::
  42.     remove_value(valType &val , BTnode<valType> *prev)
  43.     {
  44.         if (val < _val)
  45.         {
  46.             if( !_lchild )
  47.                 return ;
  48.             else
  49.             {
  50.                 _lchild->remove_value(val,_lchild);
  51.             }
  52.         }
  53.         else
  54.         if (val > _val)
  55.         {
  56.             if( !_rchild )
  57.                 return ;
  58.             else
  59.             {
  60.                 _rchild->remove_value(val,_rchild);
  61.             }
  62.         }
  63.         else
  64.         {
  65.             if(_rchild)
  66.             {
  67.                 prev = _rchild;
  68.                 if(_lchild)
  69.                 {
  70.                     if(!prev -> _lchild )
  71.                         prev->_lchild =_lchild;
  72.                     else
  73.      [quote]                   BTnode<valType>::lchild_leaf(_lchild,prev->_lchild);
  74.                 }
  75.             }
  76.             else
  77.                 prev = _lchild;
  78.             delete this;

  79.         }
  80.     }
复制代码



BinaryTree.h
  1. #ifndef BINARYTREE_H_INCLUDED
  2. #define BINARYTREE_H_INCLUDED

  3. #include "BTnode.h"
  4. #include <iostream>
  5. using namespace std;

  6. template <typename elemType>
  7. class BinaryTree
  8. {
  9. public:
  10.     BinaryTree() ;
  11.     BinaryTree(const BinaryTree& );
  12.     ~BinaryTree() ;
  13.     BinaryTree& operator = (const BinaryTree& );
  14.     ostream& print(ostream& os) const ; //中序遍历

  15.     void insert(const elemType &elem);
  16.     void remove( const elemType &elem);
  17.     void remove_root( const elemType &elem);
  18.     bool empty() {return _root;}
  19.     void clear();
  20. private:
  21.     void clear(BTnode<elemType> *pt);
  22.     BTnode<elemType>* _root;
  23.     void copy(BTnode<elemType> *tar,BTnode<elemType> *src);
  24. };

  25. #endif // BINARYTREE_H_INCLUDED
复制代码


BinaryTree.cpp
  1. #include "BinaryTree.h"

  2. template <typename elemType>
  3. inline BinaryTree<elemType>::BinaryTree() :_root(0) {}

  4. template <typename elemType>
  5. inline BinaryTree<elemType>::BinaryTree(const BinaryTree &rhs)
  6.     {
  7.         copy(_root,rhs._root);
  8.     }

  9. template <typename elemType>
  10. inline BinaryTree<elemType>::~BinaryTree()
  11.     {
  12.         clear();
  13.     }

  14. template <typename elemType>
  15. inline BinaryTree<elemType>&
  16. BinaryTree<elemType>::
  17.     operator =  (const BinaryTree &rhs)
  18.     {
  19.         if(this != rhs)
  20.             clear();
  21.         copy(_root,rhs._root);
  22.         return *this;
  23.     }

  24. template <typename elemType>
  25. inline void BinaryTree<elemType>::
  26.     insert(const elemType &elem)
  27.     {
  28.         if( ! _root )
  29.             _root = new BTnode<elemType>(elem);
  30.         else
  31.             _root->inset_value(elem);
  32.     }

  33. template <typename elemType>
  34. inline void BinaryTree<elemType>::
  35.     remove(const elemType &elem)
  36.     {
  37.         if (_root)
  38.         {
  39.             if(_root->_val == elem)
  40.                 remove_root();  //删除根节点
  41.             else
  42.                 _root->remove_value(elem , _root); // 删除_root二叉树中的值为elem的结点
  43.         }
  44.     }

  45. template <typename elemType>
  46. inline void BinaryTree<elemType>::
  47.     remove_root (const elemType &elem)
  48.     {
  49.         BTnode<elemType> *p = _root; //指向准备删除的根节点
  50.         if (! _root)
  51.             return ;
  52.         if (_root->_rchild)
  53.         {
  54.             _root = _root->_rchild;
  55.             if( _root->_lchild )
  56.             {
  57.                 BTnode<elemType> *lc = p->_lchild;//指向待处理的根节点的左子树
  58.                 BTnode<elemType> *newlc = _root->_lchild;//新根节点的左子树
  59.                 if(! newlc)
  60.                     _root->_rchild = lc;
  61.                 else
  62.                     BTnode<elemType>::lchild_leaf(lc ,newlc);
  63.             }
  64.         }
  65.         else
  66.             _root = p->_lchild;
  67.         delete p;
  68.     }


  69. template <typename elemType>
  70. inline void
  71. BinaryTree<elemType>::
  72.     clear()
  73.     {
  74.         if(_root)
  75.         {
  76.             clear(_root);
  77.             _root = 0;
  78.         }
  79.     }

  80. template<typename elemType>
  81. inline void
  82. BinaryTree<elemType>::
  83.     clear(BTnode<elemType> *pt)
  84.     {
  85.         if(pt)
  86.         {
  87.             clear(pt->_lchild);
  88.             clear(pt->_rchild);
  89.             delete(pt);
  90.         }
  91.     }

  92. template <typename elemType>
  93. inline ostream&
  94. BinaryTree<elemType>::print(ostream& os) const
  95. {
  96.     if( _root )
  97.     {
  98.         os << print( _root->_lchild );
  99.         os << _root->_val << ' ';
  100.         os << print( _root->_rchild );
  101.     }
  102.     return os;
  103. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-3-11 15:57:59 | 显示全部楼层
人造人 发表于 2021-3-11 15:44
把所有的源代码都贴出来,说明哪一个代码在哪一个源文件,我在这边帮你看看

BTnode模板实例化出现了问题,问题应该就在BTnode.cpp当中,因为我尝试直接在BTnode.h上,在类内部定义,没有出现问题。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-3-11 16:08:05 | 显示全部楼层    本楼为最佳答案   
547658697 发表于 2021-3-11 15:57
BTnode模板实例化出现了问题,问题应该就在BTnode.cpp当中,因为我尝试直接在BTnode.h上,在类内部定义, ...

对,没错
模板的声明和定义不能分开,把 BTnode.cpp 的内容合并到 BTnode.h 就可以了
  1. #ifndef BTNODE_H_INCLUDED
  2. #define BTNODE_H_INCLUDED

  3. template <typename Type>
  4. class BinaryTree;

  5. template <typename valType>
  6. class BTnode
  7. {
  8. public:
  9.     friend class BinaryTree<valType>;
  10.     BTnode(const valType &val);
  11.     void insert_value( const valType &val);
  12.     void lchild_leaf(BTnode<valType> *leaf,BTnode<valType> *subtree );
  13.     void remove_value(valType &val , BTnode<valType> *prev);
  14. private:
  15.    valType _val;
  16.    int _cnt;
  17.    BTnode* _lchild;
  18.    BTnode* _rchild;
  19. };

  20. template <typename valType>
  21. inline BTnode<valType>::
  22.     BTnode(const valType &val):_val(val)
  23.     {
  24.         _cnt=1;
  25.         _lchild=_rchild=0;
  26.     }


  27. template <typename valType>
  28. inline void BTnode<valType>::
  29.     insert_value ( const valType &val )
  30.     {
  31.         if(_val == val )
  32.             _cnt++;
  33.         if(_val < val)
  34.         {
  35.             if(! _lchild)
  36.                 _lchild = new BTnode<valType>(val);
  37.             else
  38.                 _lchild->insert_value(val);
  39.         }
  40.         if(_val > val)
  41.         {
  42.             if(! _rchild)
  43.                 _rchild = new BTnode<valType>(val);
  44.             else
  45.                 _rchild->insert_value(val);
  46.         }
  47.     }

  48. template <typename valType>
  49. inline void BTnode<valType>::
  50.     lchild_leaf(BTnode<valType> *leaf,BTnode<valType> *subtree )
  51.     {
  52.         //找到没有左孩子的结点
  53.         while (! subtree->_lchild )
  54.             subtree = subtree->_lchild;
  55.         //找到了 subtree所指结点没有左子树
  56.         subtree->_lchild = leaf;
  57.     }

  58. template <typename valType>
  59. inline void BTnode<valType>::
  60.     remove_value(valType &val , BTnode<valType> *prev)
  61.     {
  62.         if (val < _val)
  63.         {
  64.             if( !_lchild )
  65.                 return ;
  66.             else
  67.             {
  68.                 _lchild->remove_value(val,_lchild);
  69.             }
  70.         }
  71.         else
  72.         if (val > _val)
  73.         {
  74.             if( !_rchild )
  75.                 return ;
  76.             else
  77.             {
  78.                 _rchild->remove_value(val,_rchild);
  79.             }
  80.         }
  81.         else
  82.         {
  83.             if(_rchild)
  84.             {
  85.                 prev = _rchild;
  86.                 if(_lchild)
  87.                 {
  88.                     if(!prev -> _lchild )
  89.                         prev->_lchild =_lchild;
  90.                     else
  91.                         BTnode<valType>::lchild_leaf(_lchild,prev->_lchild);
  92.                 }
  93.             }
  94.             else
  95.                 prev = _lchild;
  96.             delete this;

  97.         }
  98.     }

  99. #endif // BTNODE_H_INCLUDED
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-3-11 16:15:32 | 显示全部楼层
人造人 发表于 2021-3-11 16:08
对,没错
模板的声明和定义不能分开,把 BTnode.cpp 的内容合并到 BTnode.h 就可以了

非常感谢!问题解决了。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-7-7 13:32

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表