为什么c++ class中的成员函数声明与定义在不同文件,出现链接错误???

刚刚开始学c++,在头文件LINE.h中写class的定义和成员函数的声明!

#ifndef __LINE_H__
#define __LINE_H__

#include <iostream>
using namespace std;

template <typename type>
class Line;

//节点
template <typename valtype>
class Lnode{
    friend class Line<valtype>;
public:
    Lnode(const valtype& val);

    void insert_val(const valtype& val);
    void remove_val(const valtype& val, Lnode*& prev);

    void display(ostream& os, const Lnode* node)const;
    void print(ostream& os, const Lnode* node)const;

private:
    valtype _val;
    int _cnt;
    Lnode* _next;
};

//链表
template <typename elemtype>
class Line{
public:
    Line();
    Line(const Line& line);
    ~Line();

    void insert(const elemtype& elem);
    void remove(const elemtype& elem);
    void remove_root();

    void clear();
    void print(ostream& os=cout)const;
    bool empty()const;
    Line& operator=(const Line& line);

private:
    Lnode<elemtype>* _beg;
    void copy(Lnode<elemtype>& node1, const Lnode<elemtype>& node2);
    void clear(Lnode<elemtype>* node);
};

template <typename elemtype>
ostream& operator<<(ostream& os, const Line<elemtype>& line);

#endif

,在LINE.cpp文件中写成员函数的定义

//节点
//构造函数
template <typename valtype>
Lnode<valtype>::
Lnode(const valtype& val) :_val(val)
{
    _cnt = 1;
    _next = 0;
}

//插入函数
template <typename valtype>
void Lnode<valtype>::
insert_val(const valtype& val)
{
    if (val == _val)
    {
        _cnt++;
        return;
    }
    else
    {
        if (!_next)
        {
            _next = new Lnode(val);
        }
        else
        {
            _next->insert_val(val);
        }
    }
}

//中间节点删除函数
template <typename valtype>
void Lnode<valtype>::
remove_val(const valtype& val, Lnode*& prev)
{
    if (val != _val)
    {
        if (!_next)
        {
            return;
        }
        else
        {
            _next->remove_val(val, _next);
        }
    }
    else
    {
        if (_next)
        {
            prev = _next;
        }
        else
        {
            prev = 0;
        }
        delete this;
    }
}

//打印节点
template <typename valtype>
void Lnode<valtype>::
display(ostream& os, const Lnode* node)const
{
    os << node->_val << ' ';
}

//递归打印
template <typename valtype>
void Lnode<valtype>::
print(ostream& os, const Lnode* node)const
{
    if (node)
    {
        display(os, node);
        if (node->_next)
        {
            print(os, node->_next);
        }
    }
}

//链表
//构造函数
template <typename elemtype>
Line<elemtype>::Line() :_beg(0) {}

template <typename elemtype>
Line<elemtype>::Line(const Line& line) { copy(_beg, line._beg); }

//析构函数
template <typename elemtype>
Line<elemtype>::~Line() { clear(); }

//插入节点函数
template <typename elemtype>
void Line<elemtype>::
insert(const elemtype& elem)
{
    if (!_beg)
    {
        _beg = new Lnode<elemtype>(elem);
    }
    else
    {
        _beg->insert_val(elem);
    }
}

//移除节点
template <typename elemtype>
void Line<elemtype>::
remove(const elemtype& elem)
{
    if (_beg->_val == elem)
    {
        remove_root();
    }
    else
    {
        _beg->remove_val(elem, _beg);
    }
}

//开始节点删除函数
template <typename elemtype>
void Line<elemtype>::
remove_root()
{
    _beg = _beg->_next;
    delete this;
}

//清除链表
template <typename elemtype>
void Line<elemtype>::
clear()
{
    clear(_beg);
}

//打印链表
template <typename elemtype>
void Line<elemtype>::
print(ostream& os)const
{
    _beg->print(os, _beg);
}

//是否为空
template <typename elemtype>
bool Line<elemtype>::
empty() const{ return _beg == 0; }

//赋值操作符
template <typename elemtype>
Line<elemtype>& Line<elemtype>::
operator=(const Line& line)
{
    copy(_beg, line._beg);
}

//拷贝函数
template <typename elemtype>
void Line<elemtype>::
copy(Lnode<elemtype>& node1, const Lnode<elemtype>& node2)
{
    node1._val = node2._val;
    node1._cnt = node2._cnt;
    node1._next = node2._next;
}

//清除函数
template <typename elemtype>
void Line<elemtype>::
clear(Lnode<elemtype>* node)
{
    if (node)
    {
        if (node->_next)
        {
            clear(node->_next);
        }
        delete node;
    }
}

//输出运算符
template <typename elemtype>
ostream& operator<<(ostream& os, const Line<elemtype>& line)
{
    line.print(os);
    return os;
}

,然后在test.cpp中调用成员函数总是出现链接错误

#define _CRT_SECURE_NO_WARNINGS 1

#include <string>
#include "LINE.h"

int main()
{
    Line<string> line;

    line.insert("haha");
    line.insert("hehe");
    line.insert("xixi");
    line.insert("heihei");
    cout << line << endl;
    line.remove("hehe");
    cout << line << endl;
    return 0;
}

“无法解析的外部符号,该符号在_main中引用”,但是我在.cpp文件中都引用了头文件#include "LINE.h"
但是把LINE.cpp中成员数的定义放在头文件LINE.h中就可以正常运行,这是为什么啊?求助求助

我的编译器是vs2013

阅读 2.2k
2 个回答

模板的实现要放到 h 里,不能跟声明分离。

你的整个模板类的声明跟实现都放到 h 了。模板类对应的 cpp 就不需要了。

直接贴代码不好么……截图看起来累

头文件中只看到声明 class Line;,但是这个类的成员声明和实现呢?

假设 Line 的声明和定义是全的(因为你说放 .h 里就没问题),感觉是编译的时候没有把两个 cpp 文件一起编译,是分开的就有可能造成这种问题。可以试试把 line.cpp 中的内容放在 test.cpp 里面去看看。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏