鱼C论坛

 找回密码
 立即注册
查看: 1204|回复: 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 就可以了
#ifndef BTNODE_H_INCLUDED
#define BTNODE_H_INCLUDED

template <typename Type>
class BinaryTree;

template <typename valType>
class BTnode
{
public:
    friend class BinaryTree<valType>;
    BTnode(const valType &val);
    void insert_value( const valType &val);
    void lchild_leaf(BTnode<valType> *leaf,BTnode<valType> *subtree );
    void remove_value(valType &val , BTnode<valType> *prev);
private:
   valType _val;
   int _cnt;
   BTnode* _lchild;
   BTnode* _rchild;
};

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


template <typename valType>
inline void BTnode<valType>::
    insert_value ( const valType &val )
    {
        if(_val == val )
            _cnt++;
        if(_val < val)
        {
            if(! _lchild)
                _lchild = new BTnode<valType>(val);
            else
                _lchild->insert_value(val);
        }
        if(_val > val)
        {
            if(! _rchild)
                _rchild = new BTnode<valType>(val);
            else
                _rchild->insert_value(val);
        }
    }

template <typename valType>
inline void BTnode<valType>::
    lchild_leaf(BTnode<valType> *leaf,BTnode<valType> *subtree )
    {
        //找到没有左孩子的结点
        while (! subtree->_lchild )
            subtree = subtree->_lchild;
        //找到了 subtree所指结点没有左子树
        subtree->_lchild = leaf;
    }

template <typename valType>
inline void BTnode<valType>::
    remove_value(valType &val , BTnode<valType> *prev)
    {
        if (val < _val)
        {
            if( !_lchild )
                return ;
            else
            {
                _lchild->remove_value(val,_lchild);
            }
        }
        else
        if (val > _val)
        {
            if( !_rchild )
                return ;
            else
            {
                _rchild->remove_value(val,_rchild);
            }
        }
        else
        {
            if(_rchild)
            {
                prev = _rchild;
                if(_lchild)
                {
                    if(!prev -> _lchild )
                        prev->_lchild =_lchild;
                    else
                        BTnode<valType>::lchild_leaf(_lchild,prev->_lchild);
                }
            }
            else
                prev = _lchild;
            delete this;

        }
    }

#endif // BTNODE_H_INCLUDED
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

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

回帖奖励 +1 鱼币

有个问题,这个是BinaryTree.h 文件的内容?
源文件:
//.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;
    }
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

这个是我.BTnode.cpp文件的内容,用来对BTnode.h当中的所有类声明进行定义,在这里我只截取了一部分。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

把所有的源代码都贴出来,说明哪一个代码在哪一个源文件,我在这边帮你看看
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

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

main.cpp
#include <iostream>
#include "BinaryTree.h"
#include "BTnode.h"
#include <string.h>

using namespace std;

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

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

BTnode.h
#ifndef BTNODE_H_INCLUDED
#define BTNODE_H_INCLUDED

template <typename Type>
class BinaryTree;

template <typename valType>
class BTnode
{
public:
    friend class BinaryTree<valType>;
    BTnode(const valType &val);
    void insert_value( const valType &val);
    void lchild_leaf(BTnode<valType> *leaf,BTnode<valType> *subtree );
    void remove_value(valType &val , BTnode<valType> *prev);
private:
   valType _val;
   int _cnt;
   BTnode* _lchild;
   BTnode* _rchild;
};

#endif // BTNODE_H_INCLUDED


BTnode.cpp
#include "BTnode.h"


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


template <typename valType>
inline void BTnode<valType>::
    insert_value ( const valType &val )
    {
        if(_val == val )
            _cnt++;
        if(_val < val)
        {
            if(! _lchild)
                _lchild = new BTnode<valType>(val);
            else
                _lchild->insert_value(val);
        }
        if(_val > val)
        {
            if(! _rchild)
                _rchild = new BTnode<valType>(val);
            else
                _rchild->insert_value(val);
        }
    }

template <typename valType>
inline void BTnode<valType>::
    lchild_leaf(BTnode<valType> *leaf,BTnode<valType> *subtree )
    {
        //找到没有左孩子的结点
        while (! subtree->_lchild )
            subtree = subtree->_lchild;
        //找到了 subtree所指结点没有左子树
        subtree->_lchild = leaf;
    }

template <typename valType>
inline void BTnode<valType>::
    remove_value(valType &val , BTnode<valType> *prev)
    {
        if (val < _val)
        {
            if( !_lchild )
                return ;
            else
            {
                _lchild->remove_value(val,_lchild);
            }
        }
        else
        if (val > _val)
        {
            if( !_rchild )
                return ;
            else
            {
                _rchild->remove_value(val,_rchild);
            }
        }
        else
        {
            if(_rchild)
            {
                prev = _rchild;
                if(_lchild)
                {
                    if(!prev -> _lchild )
                        prev->_lchild =_lchild;
                    else
     [quote]                   BTnode<valType>::lchild_leaf(_lchild,prev->_lchild);
                }
            }
            else
                prev = _lchild;
            delete this;

        }
    }


BinaryTree.h
#ifndef BINARYTREE_H_INCLUDED
#define BINARYTREE_H_INCLUDED

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

template <typename elemType>
class BinaryTree
{
public:
    BinaryTree() ;
    BinaryTree(const BinaryTree& );
    ~BinaryTree() ;
    BinaryTree& operator = (const BinaryTree& );
    ostream& print(ostream& os) const ; //中序遍历

    void insert(const elemType &elem);
    void remove( const elemType &elem);
    void remove_root( const elemType &elem);
    bool empty() {return _root;}
    void clear();
private:
    void clear(BTnode<elemType> *pt);
    BTnode<elemType>* _root;
    void copy(BTnode<elemType> *tar,BTnode<elemType> *src);
};

#endif // BINARYTREE_H_INCLUDED

BinaryTree.cpp
#include "BinaryTree.h"

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

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

template <typename elemType>
inline BinaryTree<elemType>::~BinaryTree()
    {
        clear();
    }

template <typename elemType>
inline BinaryTree<elemType>&
BinaryTree<elemType>::
    operator =  (const BinaryTree &rhs)
    {
        if(this != rhs)
            clear();
        copy(_root,rhs._root);
        return *this;
    }

template <typename elemType>
inline void BinaryTree<elemType>::
    insert(const elemType &elem)
    {
        if( ! _root )
            _root = new BTnode<elemType>(elem);
        else
            _root->inset_value(elem);
    }

template <typename elemType>
inline void BinaryTree<elemType>::
    remove(const elemType &elem)
    {
        if (_root)
        {
            if(_root->_val == elem)
                remove_root();  //删除根节点
            else
                _root->remove_value(elem , _root); // 删除_root二叉树中的值为elem的结点
        }
    }

template <typename elemType>
inline void BinaryTree<elemType>::
    remove_root (const elemType &elem)
    {
        BTnode<elemType> *p = _root; //指向准备删除的根节点
        if (! _root)
            return ;
        if (_root->_rchild)
        {
            _root = _root->_rchild;
            if( _root->_lchild )
            {
                BTnode<elemType> *lc = p->_lchild;//指向待处理的根节点的左子树
                BTnode<elemType> *newlc = _root->_lchild;//新根节点的左子树
                if(! newlc)
                    _root->_rchild = lc;
                else
                    BTnode<elemType>::lchild_leaf(lc ,newlc);
            }
        }
        else
            _root = p->_lchild;
        delete p;
    }


template <typename elemType>
inline void
BinaryTree<elemType>::
    clear()
    {
        if(_root)
        {
            clear(_root);
            _root = 0;
        }
    }

template<typename elemType>
inline void
BinaryTree<elemType>::
    clear(BTnode<elemType> *pt)
    {
        if(pt)
        {
            clear(pt->_lchild);
            clear(pt->_rchild);
            delete(pt);
        }
    }

template <typename elemType>
inline ostream&
BinaryTree<elemType>::print(ostream& os) const
{
    if( _root )
    {
        os << print( _root->_lchild );
        os << _root->_val << ' ';
        os << print( _root->_rchild );
    }
    return os;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

BTnode模板实例化出现了问题,问题应该就在BTnode.cpp当中,因为我尝试直接在BTnode.h上,在类内部定义,没有出现问题。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

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

template <typename Type>
class BinaryTree;

template <typename valType>
class BTnode
{
public:
    friend class BinaryTree<valType>;
    BTnode(const valType &val);
    void insert_value( const valType &val);
    void lchild_leaf(BTnode<valType> *leaf,BTnode<valType> *subtree );
    void remove_value(valType &val , BTnode<valType> *prev);
private:
   valType _val;
   int _cnt;
   BTnode* _lchild;
   BTnode* _rchild;
};

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


template <typename valType>
inline void BTnode<valType>::
    insert_value ( const valType &val )
    {
        if(_val == val )
            _cnt++;
        if(_val < val)
        {
            if(! _lchild)
                _lchild = new BTnode<valType>(val);
            else
                _lchild->insert_value(val);
        }
        if(_val > val)
        {
            if(! _rchild)
                _rchild = new BTnode<valType>(val);
            else
                _rchild->insert_value(val);
        }
    }

template <typename valType>
inline void BTnode<valType>::
    lchild_leaf(BTnode<valType> *leaf,BTnode<valType> *subtree )
    {
        //找到没有左孩子的结点
        while (! subtree->_lchild )
            subtree = subtree->_lchild;
        //找到了 subtree所指结点没有左子树
        subtree->_lchild = leaf;
    }

template <typename valType>
inline void BTnode<valType>::
    remove_value(valType &val , BTnode<valType> *prev)
    {
        if (val < _val)
        {
            if( !_lchild )
                return ;
            else
            {
                _lchild->remove_value(val,_lchild);
            }
        }
        else
        if (val > _val)
        {
            if( !_rchild )
                return ;
            else
            {
                _rchild->remove_value(val,_rchild);
            }
        }
        else
        {
            if(_rchild)
            {
                prev = _rchild;
                if(_lchild)
                {
                    if(!prev -> _lchild )
                        prev->_lchild =_lchild;
                    else
                        BTnode<valType>::lchild_leaf(_lchild,prev->_lchild);
                }
            }
            else
                prev = _lchild;
            delete this;

        }
    }

#endif // BTNODE_H_INCLUDED
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

非常感谢!问题解决了。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-11-15 03:15

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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