免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 4580 | 回复: 8
打印 上一主题 下一主题

[C++] 求助,写的类链接失败 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-08-21 20:15 |只看该作者 |倒序浏览
本帖最后由 1210603696 于 2013-08-21 20:15 编辑

我写了一个类 这是类声明:
  1. #ifndef _NAME_SPACE_ZOUXIAOHANG_
  2. #define _NAME_SPACE_ZOUXIAOHANG_

  3. #include <iostream>
  4. #include <iomanip>
  5. #include <queue>
  6. #include <assert.h>

  7. template <class T>
  8. class binary_search_tree
  9. {
  10. private:
  11.         typedef struct node_t
  12.         {
  13.                 T value;
  14.                 node_t *left;
  15.                 node_t *right;
  16.         } node, *tree;
  17. public:
  18.         typedef node *iterator;
  19.         typedef const node *const_iterator;
  20. private:
  21.         //******
  22.         tree m_root;
  23.         size_t m_num;
  24.         //******
  25.         binary_search_tree(const binary_search_tree<T>& t);
  26.         binary_search_tree& operator = (const binary_search_tree<T>& t);

  27.         void _order(const tree t, const int ctrl);//ctrl: 0:pre_order 1:in_order 2:post_order
  28.         void _display_tree(const_iterator p, int depth, int ctrl) const;//ctrl:0=root 1=left 2=right
  29.         void _make_empty(iterator p);
  30.         node* _find_node(iterator p, T x);
  31.         node* _insert_node(iterator p, T x);
  32.         node* _delete_node(iterator p, T x);
  33. public:
  34.         binary_search_tree():m_root(NULL), m_num(0){}
  35.         ~binary_search_tree();

  36.         iterator find_node(T x);
  37.         iterator find_max();
  38.         iterator find_min();
  39.         bool insert_node(T x);
  40.         iterator delete_node(T x);
  41.         void make_empty();
  42.         bool empty();
  43.         size_t size();
  44.         void pre_order();
  45.         void in_order();
  46.         void post_order();
  47.         void level_order();
  48.         const_iterator root();
  49.         void display_tree() const;//ctrl:0=root 1=left 2=right
  50.         void display_tree();//ctrl:0=root 1=left 2=right
  51. };

  52. template <class T>
  53. std::ostream& operator<<(std::ostream& os, const binary_search_tree<T>& t);

  54. #endif
复制代码
下面是实现文件:
  1. #include "./binary_search_tree.h"

  2. template <class T>
  3. void binary_search_tree<T>::_order(const tree t, const int ctrl)//ctrl: 0:pre_order 1:in_order 2:post_order
  4. {
  5.         if(0 == ctrl)
  6.         {
  7.                 if(NULL != t)
  8.                 {
  9.                         std::cout<<t->value<<" ";
  10.                         _order(t->left, 0);
  11.                         _order(t->right, 0);
  12.                 }
  13.         }
  14.         else if(1 == ctrl)
  15.         {
  16.                 if(NULL != t)
  17.                 {
  18.                         _order(t->left, 1);
  19.                         std::cout<<t->value<<" ";
  20.                         _order(t->right, 1);
  21.                 }
  22.         }
  23.         else if(2 == ctrl)
  24.         {
  25.                 if(NULL != t)
  26.                 {
  27.                         _order(t->left, 2);
  28.                         _order(t->right, 2);
  29.                         std::cout<<t->value<<" ";
  30.                 }
  31.         }
  32. }
  33. template <class T>
  34. void binary_search_tree<T>::_display_tree(const_iterator p, int depth, int ctrl) const//ctrl:0=root 1=left 2=right
  35. {
  36.         if(NULL == p)
  37.                 return ;
  38.         std::cout<<std::setw(depth);
  39.         if(0 == ctrl)
  40.                 std::cout<<"root:";
  41.         else if(1 == ctrl)
  42.                 std::cout<<"left";
  43.         else if(2 == ctrl)
  44.                 std::cout<<"right";
  45.         std::cout<<p->value<<std::endl;
  46.         _display_tree(p->left, depth+6, 1);
  47.         _display_tree(p->right, depth+6, 2);
  48. }
  49. template <class T>
  50. void binary_search_tree<T>::_make_empty(iterator p)
  51. {
  52.         if(NULL != p)
  53.         {
  54.                 _make_empty(p->left);
  55.                 _make_empty(p->right);
  56.                 delete p;
  57.         }
  58. }
  59. template <class T>
  60. typename binary_search_tree<T>::iterator binary_search_tree<T>::_insert_node(iterator p, T x)
  61. {
  62.         if(NULL == p)
  63.         {
  64.                 p = new        node;
  65.                 assert(NULL != p);
  66.                 p->value = x;
  67.                 p->left = p->right = NULL;
  68.                 ++m_num;
  69.         }
  70.         else if(x < p->value)
  71.                 p->left = _insert_node(p->left, x);
  72.         else if(x > p->value)
  73.                 p->right = _insert_node(p->right, x);

  74.         return p;
  75. }
  76. template <class T>
  77. typename binary_search_tree<T>::iterator binary_search_tree<T>::_delete_node(iterator p, T x)
  78. {
  79.         if(NULL == p)
  80.                 return NULL;
  81.         if(x < p->value)
  82.                 p->left = _delete_node(p->left, x);
  83.         else if(x > p->value)
  84.                 p->right = _delete_node(p->right, x);
  85.         else
  86.         {
  87.                 iterator tmp = NULL;
  88.                 if(p->left && p->right)// p has two childs
  89.                 {
  90.                         tmp = m_root;
  91.                         m_root = p->right;
  92.                         p->value = find_min()->value;
  93.                         m_root = tmp;
  94.                         p->right = _delete_node(p->right, p->value);
  95.                 }
  96.                 else
  97.                 {
  98.                         tmp = p;
  99.                         if(!p->left)
  100.                                 p = p->right;
  101.                         else if(!p->right)
  102.                                 p = p->left;
  103.                         delete tmp;
  104.                         --m_num;
  105.                 }
  106.         }
  107.         return p;
  108. }
  109. template <class T>
  110. typename binary_search_tree<T>::iterator binary_search_tree<T>::_find_node(iterator p, T x)
  111. {
  112.         if(NULL == p)
  113.                 return NULL;
  114.         if(x < p->value)
  115.                 return _find_node(p->left, x);
  116.         else if(x > p->value)
  117.                 return _find_node(p->right, x);
  118.         else
  119.                 return p;
  120. }

  121. template <class T>
  122. binary_search_tree<T>::~binary_search_tree()
  123. {
  124.         make_empty();
  125. }
  126. template <class T>
  127. typename binary_search_tree<T>::iterator binary_search_tree<T>::find_node(T x)
  128. {
  129.         return _find_node(m_root, x);
  130. }
  131. template <class T>
  132. typename binary_search_tree<T>::iterator binary_search_tree<T>::find_max()
  133. {
  134.         node *p = m_root;
  135.         while(NULL != p && NULL != p->right)
  136.                 p = p->right;
  137.         return p;
  138. }
  139. template <class T>
  140. typename binary_search_tree<T>::iterator binary_search_tree<T>::find_min()
  141. {
  142.         node *p = m_root;
  143.         while(NULL != p && NULL != p->left)
  144.                 p = p->left;
  145.         return p;
  146. }
  147. template <class T>
  148. bool binary_search_tree<T>::insert_node(T x)
  149. {
  150.         return (m_root = _insert_node(m_root, x)) == NULL ? false : true;
  151. }
  152. template <class T>
  153. typename binary_search_tree<T>::iterator binary_search_tree<T>::delete_node(T x)
  154. {
  155.         return _delete_node(m_root, x);
  156. }
  157. template <class T>
  158. void binary_search_tree<T>::make_empty()
  159. {
  160.         _make_empty(m_root);
  161.         m_root = NULL;
  162.         m_num = 0;
  163. }
  164. template <class T>
  165. bool binary_search_tree<T>::empty()
  166. {
  167.         return m_num == 0;
  168. }
  169. template <class T>
  170. size_t binary_search_tree<T>::size()
  171. {
  172.         return m_num;
  173. }
  174. template <class T>
  175. void binary_search_tree<T>::pre_order()
  176. {
  177.         if(NULL != m_root)
  178.                 _order(m_root, 0);
  179. }
  180. template <class T>
  181. void binary_search_tree<T>::in_order()
  182. {
  183.         if(NULL != m_root)
  184.                 _order(m_root, 1);
  185. }
  186. template <class T>
  187. void binary_search_tree<T>::post_order()
  188. {
  189.         if(NULL != m_root)
  190.                 _order(m_root, 2);
  191. }
  192. template <class T>
  193. void binary_search_tree<T>::level_order()
  194. {
  195.         if(NULL == m_root)
  196.                 return ;
  197.         iterator p = m_root;
  198.         std::queue<node*> q;
  199.         q.push(p);
  200.         while(!q.empty())
  201.         {
  202.                 p = q.front();
  203.                 std::cout<<p->value<<" ";
  204.                 if(NULL != p->left)
  205.                         q.push(p->left);
  206.                 if(NULL != p->right)
  207.                         q.push(p->right);
  208.                 q.pop();
  209.         }
  210. }
  211. template <class T>
  212. typename binary_search_tree<T>::const_iterator binary_search_tree<T>::root()
  213. {
  214.         return m_root;
  215. }
  216. template <class T>
  217. void binary_search_tree<T>::display_tree() const
  218. {
  219.         _display_tree(m_root, 2, 0);
  220. }
  221. template <class T>
  222. void binary_search_tree<T>::display_tree()
  223. {
  224.         _display_tree(m_root, 2, 0);
  225. }


  226. template <class T>
  227. std::ostream& operator<<(std::ostream& os, const binary_search_tree<T>& t)
  228. {
  229.         t.display_tree();
  230.         return os;
  231. }
复制代码
我写了一个例程来测试我的binary_tree:
  1. #include "binary_search_tree.h"

  2. int main(int argc, char const *argv[])
  3. {
  4.         binary_search_tree<int> t;
  5.         binary_search_tree<int>::iterator it;
  6.     t.make_empty();
  7.     t.insert_node(10);
  8.         return 0;
  9. }
复制代码
我编译链接的时候codeblock给出了下面错误:
obj\Debug\main.o||In function `main'
C:\Users\zxh\Desktop\test\main.cpp|7|undefined reference to `binary_search_tree<int>::make_empty()'|
C:\Users\zxh\Desktop\test\main.cpp|8|undefined reference to `binary_search_tree<int>::insert_node(int)'|
C:\Users\zxh\Desktop\test\main.cpp|9|undefined reference to `binary_search_tree<int>::~binary_search_tree()'|
C:\Users\zxh\Desktop\test\main.cpp|9|undefined reference to `binary_search_tree<int>::~binary_search_tree()'|
||=== Build finished: 4 errors, 0 warnings ===|

我找了很久实在是不知道为什么会链接失败,我明明生成了binary_tree.o并链接进来了啊,在ubuntu下g++ binary_tree.o main.c -o main也提示同样的问题

论坛徽章:
0
2 [报告]
发表于 2013-08-21 21:09 |只看该作者
把测试例程写在binary_tree.cpp下是可以成功运行的

论坛徽章:
4
水瓶座
日期:2013-09-06 12:27:30摩羯座
日期:2013-09-28 14:07:46处女座
日期:2013-10-24 14:25:01酉鸡
日期:2014-04-07 11:54:15
3 [报告]
发表于 2013-08-21 21:26 |只看该作者
模板不支持分离编译啊

论坛徽章:
0
4 [报告]
发表于 2013-08-21 21:33 |只看该作者
不可能不支持啊,你把我的代码编译链接一下看看是不是也是失败回复 3# linux_c_py_php


   

论坛徽章:
17
处女座
日期:2013-08-27 09:59:352015亚冠之柏太阳神
日期:2015-07-30 10:16:402015亚冠之萨济拖拉机
日期:2015-07-29 18:58:182015年亚洲杯之巴勒斯坦
日期:2015-03-06 17:38:17摩羯座
日期:2014-12-11 21:31:34戌狗
日期:2014-07-20 20:57:32子鼠
日期:2014-05-15 16:25:21亥猪
日期:2014-02-11 17:32:05丑牛
日期:2014-01-20 15:45:51丑牛
日期:2013-10-22 11:12:56双子座
日期:2013-10-18 16:28:17白羊座
日期:2013-10-18 10:50:45
5 [报告]
发表于 2013-08-21 21:45 |只看该作者
回复 2# 1210603696

通常模板的定义也应该放在头文件中实现,你在binary_tree.cpp中调用成功是因为模板的定义和调用都在一个translate unit中。引发这个问题的原因是模板的“两阶段查找”造成的。具体的说是在第二个阶段进行模板实例化时产生的。当实例化模板时(在实例化点POI)相应模板定义必须是可见的。如果调用模板的代码位同binary_tree.cpp,在你的代码中恰好满足在一个translate unit中模板的定义可见,所以没有问题,但如果调用模板的代码在另一个文件中就会找不到模板的定义所以出错了。把模板声明和定义放在一个文件中既所谓的“包含模型”,虽然C++标准也说明了可把把模板定义放到cpp中,既所谓的“分离模型”,但要求显示使用export关健字,而且很多编译器都支持的不好,所以“包含模型”是实际的标准。
   

论坛徽章:
0
6 [报告]
发表于 2013-08-21 21:48 |只看该作者
回复 5# myworkstation
那难道项目中都要将模版实现放在.h文件里?


   

论坛徽章:
0
7 [报告]
发表于 2013-08-21 21:49 |只看该作者
回复 5# myworkstation
嗯!我把模版的实现放在了.h文件里,程序能运行了,谢谢了

   

论坛徽章:
17
处女座
日期:2013-08-27 09:59:352015亚冠之柏太阳神
日期:2015-07-30 10:16:402015亚冠之萨济拖拉机
日期:2015-07-29 18:58:182015年亚洲杯之巴勒斯坦
日期:2015-03-06 17:38:17摩羯座
日期:2014-12-11 21:31:34戌狗
日期:2014-07-20 20:57:32子鼠
日期:2014-05-15 16:25:21亥猪
日期:2014-02-11 17:32:05丑牛
日期:2014-01-20 15:45:51丑牛
日期:2013-10-22 11:12:56双子座
日期:2013-10-18 16:28:17白羊座
日期:2013-10-18 10:50:45
8 [报告]
发表于 2013-08-21 21:53 |只看该作者
回复 6# 1210603696

通常来讲是这样子的,你可以看看stl基本上都是这么干的。
   

论坛徽章:
0
9 [报告]
发表于 2013-08-21 22:30 |只看该作者
linux_c_py_php 发表于 2013-08-21 21:26
模板不支持分离编译啊


倒没说不支持,主要是编译链接时能看到相应的实现,C++标准有个export关键字修改类定义,用来支持模板分离编译模式,不过很多编译器可能不支持export关键词。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP