C++ learning-关于 error LNK2019以及error C2244的 解决方案

1 篇文章 0 订阅
1 篇文章 0 订阅

博主在学习数据结构(C++版,邓俊辉)时,发现敲打书上代码报错,其错误类型是error LNK2019以及error C2244:第一个错误表示:使用了无法解析的外部符号,说明定义和声明没有衔接上,所以=和[]操作符重载失败,因为我是类模板的定义和成员函数定义分别放在h和cpp文件中的,我将报错的函数定义直接移到头文件中,暂时解决了第一个错误。而第二个错误表示:无法将函数定义与现有的声明匹配,但是我仔细检查了定义和匹配是一模一样的,而且我在头文件中是用了#ifndef和#define来防止头文件被重复包含


博主仔细思考后,感觉是跟模板类的编写规则有关,就回去查阅了c++ primer 讲模板类的部分。发现这个错误是与模板编译类型有关!模板编译类型分为:“包含”模型“分别编译”模型。因为博主所用的编译器是VS2012,只支持包含模型,重点介绍包含模型来解决上面的问题。解决方案:在类模板的头文件定义类结束后加上#include “模板类名.cpp”,例如:
解决方案1:

// header file Vector.h
#ifndef VECTOR_H
#define VECTOR_H
template <class T> class Vector{
//成员和成员函数声明或定义
};
#include "Vector.cpp" //包含在头文件中只声明的成员函数的定义,一定记得加!
#endif

若只是这样,你可能仍然会报错:重复定义或声明某个函数,你还需要做这样的操作

// Vector.cpp
#ifndef VECTOR_CPP
#define VECTOR_CPP
...//定义那些成员函数

#endif

这样解决重复定义问题,你的程序可以重新运行了!
“分别编译”模型:

一句话:就是在cpp文件一开始加上export templateclass 你的类名然后再#include “你的模板类名.h” 成员函数定义…;由于VS2012貌似不支持,所以我也无法演示和验证该方法能否解决问题。。

注意:包含模型的解决方法不适于特化函数和模板函数都放在cpp文件中定义的情况,这种情况下两种办法:1.在特化函数定义加上inline ,将其声明为内联函数。2.使用笨方法,将模板函数定义放于头文件定义中,将特化函数定义放于cpp文件中,具体可参考这篇博客,讲解很详细 。
http://blog.csdn.net/lh844386434/article/details/6713361

第一次写博客,不足之处还请指导和见谅!大家觉得有用的请点个赞~

附我的例子代码参考(源于数据结构(C++语言版)第三版):

// Vector.h
#ifndef VECTOR_H_
#define VECTOR_H_

typedef int Rank;
#define DEFAULT_CAPACITY 3

template <typename T> class Vector{
protected :
    Rank _size; int _capacity; T* _elem;
    void copyFrom(T const* A,Rank lo,Rank hi);
    void expand();
    void shrink();
    bool bubble(Rank lo,Rank hi);
    void bubbleSort(Rank lo,Rank hi);
    Rank max(Rank lo,Rank hi);
    void selectionSort(Rank lo,Rank hi);
    void merge(Rank lo,Rank mi,Rank hi);
    void mergeSort(Rank lo,Rank hi);
    Rank partition(Rank lo,Rank hi);
    void quickSort(Rank lo,Rank hi);
    void heapSort(Rank lo, Rank hi);
public:
//构造函数
    Vector(int c = DEFAULT_CAPACITY, int s=0,T v=0)
    {
        _elem= new T[_capacity=c];
        for (_size=0;_size<s;_elem[_size++]=v);
    }
    Vector (T const* A,Rank n){
        copyFrom(A,0,n);
    }
    Vector (T const* A,Rank lo,Rank hi){
        copyFrom(A,lo,hi);
    }
    Vector (Vector<T> const& V){
        copyFrom(V._elem,0,V._size);
    }
    Vector (Vector<T> const& V,Rank lo,Rank hi){
        copyFrom(V._elem,lo,hi);
    }
//析构函数
    ~Vector()
    {
        delete [] _elem;
    }
// 只读访问接口
    Rank size() const 
    {
        return _size;
    }
    bool empty() const{
        return _size;
    }
    int disordered() const;
    Rank find (T const& e) const{
        return find(e,0,_size);
    }
    Rank find(T const& e,Rank lo,Rank hi ) const;
    Rank search(T const& e) const{
        return (0>=_size)?-1:search(e,0,_size);
    }
    Rank search(T const& e,Rank lo,Rank hi) const;
//可写访问接口
    T& operator[](Rank r) const;
    Vector<T> & operator=(Vector<T> const&);
    T remove(Rank r);
    int remove(Rank lo,Rank hi);
    Rank insert(Rank r,T const& e);
    Rank insert(T const& e){
        return insert(_size,e);
    }
    void sort(Rank lo,Rank hi);
    void sort(){
        sort(0,_size);
    }
    void unsort(Rank lo,Rank hi);
    void unsort(){
        unsort(0,_size);
    }
    int deduplicate();
    int uniquify();
//遍历
    void traverse(void(*) (T&));
    template<typename VST> void traverse(VST&);
};
#include "Vector.cpp"
#endif
// Vector.cpp
#ifndef VECTOR_C_
#define VECTOR_C_
#include "Vector.h"
template <typename T> void Vector<T>::copyFrom(T const* A,Rank lo,Rank hi){
    _elem=new T[_capacity=2*(hi-lo)];
    _size=0;
    while(lo<hi)
        _elem[_size++] = A[lo++];
}

template <typename T> Vector<T>& Vector<T>::operator=(Vector<T> const& V){
    if (_elem) 
        delete [] _elem;
    copyFrom(V._elem,0,V.size());
    return *this;
}

template <typename T>void Vector<T>::expand()
{
    if (_size< _capacity) return;
    if (_capacity < DEFAULT_CAPACITY) 
        _capacity=DEFAULT_CAPACITY;
    T* oldElem= _elem; _elem= new T[_capacity<<1];
    for (int i=0;i<_size;i++)
        _elem[i]=oldElem[i];
    delete [] oldElem;
}

template <typename T> void Vector<T>::shrink()
{
    if (_capacity<DEFAULT_CAPACITY <<1) return;
    if (_size <<2 > _capacity) return;
    T* oleElem=_elem; _elem=new T[_capacity >>1];
    for (int i=0;i<_size;i++)
        _elem[i]=oleElem[i];
    delete [] oleElem;
}

template <typename T> T& Vector<T>::operator[] (Rank r) const
{
    return _elem[r];
}

template <typename T> void permute(Vector<T>& V)
{
    for (int i=V.size();i>0;i--)
        swap(V[i-1],V[rand() % i]);
}

template <typename T> void Vector<T>::unsort(Rank lo,Rank hi){
    T* V=_elem+lo;
    for (Rank i=hi-lo;i>0;i--)
        swap(V[i-1],V[rand() % i]);
}

template <typename T> static bool lt(T* a,T* b){ return lt(*a,*b);}
template <typename T> static bool lt(T& a,T& b){ return a<b;}
template <typename T> static bool eq(T* a,T* b){ return eq(*a,*b);}
template <typename T> static bool eq(T& a,T& b){ return a==b;}

template <typename T>
Rank Vector<T>::find(T const& e,Rank lo,Rank hi) const{
    while ((lo<hi--) && (e!=_elem[hi])); //(0,n),首先执行lo<hi--,则hi=n-1,_elem[hi]正确;当hi=1时,执行完e!=_elem[0]后还是执行一次lo<hi--,则hi=lo-1!
    return hi;
}

template <typename T>
Rank Vector<T>::insert (Rank r, T const& e){
    expand();
    for (int i=_size;i>r;i--)
        _elem[i]=_elem[i-1];
    _elem[r]=e;
    _size++;
    return r;
}

template <typename T> int Vector<T>::remove(Rank lo,Rank hi){
    if (lo==hi) return 0;
    while (hi<_size) _elem[lo++]=_elem[hi++];
    _size=lo;
    shrink();
    return hi-lo;
}

template <typename T> T Vector<T>::remove(Rank r){
    T e=_elem[r];
    remove(r,r+1);
    return e;
}

template <typename T> int Vector<T>::deduplicate(){
    int oldsize=_size;
    Rank i=1;
    while (i<_size)
        (find(_elem[i],o,i))<0? i++ :remove(i);
    return oldsize-_size;
}

template <typename T> void Vector<T>::traverse (void (*visit) (T&))
{
    for (int i=0;i<_size;i++)
        visit(_elem[i]);
}

template <typename T> template <typename VST>
void Vector<T>::traverse(VST &visit)
{
    for (int i=0;i<_size;i++)
        visit(_elem[i]);

}

template <typename T> struct Increase
{
    virtual void operator() (T& e){
        e++;
    }
};

template <typename T> void increase (Vector<T> &V)
{
    V.traverse(Increase<T>());
}

template <typename T> int Vector<T>::disordered() const{
    int n=0;
    for (int i=1;i<_size;i++)
        if (_elem[i-1]>_elem[i]) n++;
    return n;
} //n=0有序

template <typename T> int Vector<T>::uniquify() {     //有序向量重复元素剔除算法(高效版)
    Rank i=0,j=0;
    while(++j<_size)
        if (_elem[i]!=_elem[j])
        {
            _elem[++i]=_elem[j];
        }
        _size=++i;
        shrink();
        return j-i;
}

//有序查找为search()
//template <typename T> static Rank binSearch(T *A,T const& e,Rank lo,Rank hi){ //版本A
//  while (lo<hi){
//      Rank mi=(lo+hi)>>1;
//      if (e<A[mi])
//          hi=mi;
//      else if (e>A[mi])
//          lo=mi;
//      else
//          return mi;
//  }
//  return -1;
//}

//template <typename T> static Rank binSearch(T* A,T cosnt& e,Rank lo,Rank hi){ //版本B
//  while (1<hi-lo){
//      Rank mi=(lo+hi)>>1;
//      (e<A[mi])?hi=mi:lo=mi;
//  }
//  return (e==A[lo])?lo:-1;
//}

template <typename T> static Rank binSearch(T* A,T const& e,Rank lo,Rank hi){ //版本C,返回小于等于e的秩最大者
    while (lo<hi){
        Rank mi=(lo+hi)>>1;
        (e<A[mi])?hi=mi:lo=mi+1;
    }
    return --lo;
}

#include "Fib.h" //自己编写Fib.h
template <typename T> static Rank fibSearch(T* A,T const& e,Rank lo,Rank hi){
    Fib fib(hi-lo);
    while (lo<hi){
        while (hi-lo<fib.get()) fib.prev();
        Rank mi=lo+fib.get()-1;
        if (e<A[mi]) hi=mi;
        else if (e>A[mi]) lo=mi;
        else 
            return mi;
    }
    return -1;
}


template <typename T>
Rank Vector<T>::search(T const& e,Rank lo,Rank hi) const{
    return (rand() % 2)? binSearch(_elem,e,lo,hi):fibSearch(_elem,e,lo,hi);
}

template <typename T> void Vector<T>::sort (Rank lo,Rank hi){
    switch (rand()%5)
    {
    case 1:
    case 2:bubbleSort(lo,hi);break;
    case 3:
    case 4:mergeSort(lo,hi);break;
    default:
        mergeSort(lo,hi);break;
        break;
    }
}

template<typename T> bool Vector<T>::bubble(Rank lo,Rank hi){
    bool sorted=true;
    while(++lo<hi)
    {
        if (_elem[lo-1]>_elem[lo]){
            sorted=false;
            swap(_elem[lo-1],_elem[lo]);
        }
    }
    return sorted;
}

template <typename T> void Vector<T>::bubbleSort(Rank lo,Rank hi)
{
    while(!bubble(lo,hi--)) ;
}

template<typename T> void Vector<T>::merge(Rank lo,Rank mi,Rank hi){
    T* A=_elem+lo;
    int lb=mi-lo;
    T *B=new T[lb];
    for (Rank i=0;i<lb;B[i]=A[i++]);
    int lc=hi-mi; T* C=_elem+mi;
    for (Rank i=0,j=0,k=0;(j<lb) ||(k<lc);){
        if ((j<lb) && (!(k<lc) || B[j]<=C[k])) A[i++] =B[j++];
        if ((k<lc) && (!(j<lb) || C[k]<B[j]))  A[i++]=C[k++];
    }
    delete [] B;
}

template <typename T> void Vector<T>::mergeSort(Rank lo,Rank hi){
    if (hi-lo <2) return;
    int mi=(hi+lo)/2;
    mergeSort(lo,mi);
    mergeSort(mi,hi);
    merge(lo,mi,hi);
}

#endif
// main.cpp 测试Vector部分功能
#include <iostream>
#include "Vector.h"
#include "Fib.h"
using namespace std;

int main(int argc,char* argv[])
{
    const int a[]={1,3,4,7,2,5,9,6,8};
    Vector<int> v1(a,9),v2;
    v2=v1;
    cout<<"v1: ";
    permute(v1);
    for (int i=0;i<v1.size();i++)
        cout<<v1[i]<<" ";
    cout<<endl;
    cout<<"v2: ";
    for (int i=0;i<v2.size();i++)
        cout<<v2[i]<<" ";
    cout<<endl; 
    int flag=v2.find(5,0,9);
    cout<<flag<<endl;
    v2.insert(4,10);
    cout<<"v2: ";
    for (int i=0;i<v2.size();i++)
        cout<<v2[i]<<" ";
    cout<<endl; 
    v2.remove(4,5);
    cout<<"v2: ";
    for (int i=0;i<v2.size();i++)
        cout<<v2[i]<<" ";
    cout<<endl; 
    v1.sort(0,9);
    cout<<"v1: ";
    for (int i=0;i<v1.size();i++)
        cout<<v1[i]<<" ";
    cout<<endl; 
    return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
LNK2019错误是一个链接错误,指示在编译时找不到外部符号的定义或解析。这个错误通常发生在链接器无法解析函数、变量或对象的引用时。在你提供的引用中,LNK2019错误的消息显示无法解析外部符号“_lws_create_context@4”,该符号在“WebsocketServerApp::startServer”函数中被引用。 该错误通常是由以下几种情况引起的: 1. 缺少对相关函数或变量的定义或声明。 2. 函数或变量的声明与其定义不匹配。 3. 编译器没有找到相关的库文件或链接器没有将库文件添加到项目中。 要解决这个问题,可以尝试以下几个步骤: 1. 确保你的代码中包含了正确的函数或变量声明,以及它们的定义。 2. 检查函数或变量的声明和定义是否匹配,包括参数类型和返回类型。 3. 确保你的项目中包含了相关的库文件,并将它们添加到链接器的输入选项中。 通过检查这些方面,你应该能够解决LNK2019错误并成功编译你的代码。<span class="em">1</span> #### 引用[.reference_title] - *1* [VS报错 --- error LNK2019: 无法解析外部符号](https://blog.csdn.net/bigger_belief/article/details/131241862)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值