VS里把模板类的声明和定义分开写,编译时报LNK2019无法解析的外部符号,求正确的使用方法。

zsyhnxc 2015-12-01 03:03:41
这是类的声明String.h
#ifndef TEMPLATE_STRING
#define TEMPLATE_STRING

template<class C> class String
{
struct Srep;
Srep* rep_;
public:
String();
String(const C*);
String(const String&);
String& operator=(const C*);
String& operator=(const String&);
~String();

class Range {};

void check(int)const;
C read(int)const;
void write(int, C);

C operator[](int)const;
int size()const;

String& operator+=(const String&);
String& operator+=(const C*);
public:
struct Srep {
C* s_;
int sz_;
int n_;
Srep(int, const C*);
~Srep();
Srep* get_own_copy();
void assign(int, const C*);
private:
Srep(const Srep&);
Srep& operator=(const Srep&);
};
};
#endif // !TEMPLATE_STRING

这是类的定义String.cpp
#include "stdafx.h"
#include "String.h"
template<class C> String<C>::Srep::Srep(int nsz, const C* p) {
n_ = 1;
sz_ = nsz;
s_ = new C[sz_ + 1];
memcpy_s(s_, sz_, p, nsz);
}

template<class C> String<C>::Srep::~Srep() {
delete[] s_;
}

template<class C> typename String<C>::Srep* String<C>::Srep::get_own_copy() {
if (n_ == 1)
return this;
n_--;
return new Srep(sz_, s_);
}

template<class C> void String<C>::Srep::assign(int nsz, const C* p) {
if (sz_ != nsz) {
delete[] s_;
sz_ = nsz;
s_ = new C[sz_ + 1];
}
memcpy_s(s_, sz_, p, nsz);
}

template<class C> String<C>::String() {
rep_ = new Srep(0, "");
}

template<class C> String<C>::String(const C* p) {
rep_ = new Srep(strlen(p), p);
}

template<class C> String<C>::String(const String& x) {
x.rep_->n_++;
rep_ = x.rep_;
}

template<class C> String<C>& String<C>::operator=(const C* p) {
if (rep_->n_ == 1) {
rep_->assign(strlen(p), p);
}
else {
rep_->n_--;
rep_ = new Srep(strlen(p), p);
}
return *this;
}

template<class C> String<C>& String<C>::operator=(const String& x) {
x.rep_->n_++;
if (--rep_->n_ == 0) {
delete rep_;
}
rep_ = x.rep_;
return *this;
}

template<class C> String<C>::~String() {
if (--rep_->n_ == 0) {
delete rep_;
}
}

template<class C> void String<C>::check(int i)const {
if (i < 0 || rep_->sz_ <= i) {
throw Range();
}
}

template<class C> C String<C>::read(int i)const {
return rep_->s_[i];
}

template<class C> void String<C>::write(int i, C c) {
rep_ = rep_->get_own_copy();
rep_->s_[i] = c;
}

template<class C> C String<C>::operator[](int i)const {
check(i);
return rep_->s_[i];
}

template<class C> int String<C>::size()const {
return rep_->sz_;
}

template<class C> String<C>& String<C>::operator+=(const String<C>& str) {
strcat_s(rep_->s_, strlen(str.rep_->s_), str.rep_->s_);
rep_->sz_ += strlen(str.rep_->s_);
return *this;
}

template<class C> String<C>& String<C>::operator+=(const C* p) {
int size = strlen(rep_->s_) + strlen(p) + 1;
C* cp = new C[size];
strncpy_s(cp, size, rep_->s_, strlen(rep_->s_));
strncat_s(cp, size, p, strlen(p));
rep_->assign(strlen(cp), cp);
return *this
}

这个是测试main函数
#include "stdafx.h"
#include "String.h"
#include "string"
#include <iostream>

int main() {
std::string s = "abcd";
String<char> ms(s.c_str());
std::cout << "no error" << std::endl;
}

如果把这个main函数写到String.cpp里,是可以通过编译并运行的,但是写到另一个.cpp文件里就不行,编译时报
LNK2019 无法解析的外部符号 "public: __thiscall String<char>::String<char>(char const *)" (??0?$String@D@@QAE@PBD@Z),该符号在函数 _main 中被引用
感觉应该是连接器的问题,但又不知道是哪里不对,求帮助,谢谢。
...全文
351 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
paschen 版主 2015-12-01
  • 打赏
  • 举报
回复
模板类不支持分离编译 原因看:http://blog.sina.com.cn/s/blog_46625a5f010000ld.html
fefe82 2015-12-01
  • 打赏
  • 举报
回复
在 String.cpp 最后加一句: template class String<char>; 试试
lm_whales 2015-12-01
  • 打赏
  • 举报
回复
大致是这样的,不过可能编译器仅仅是生成 call 0 这个 0 作占位符,因为不是汇编语言,指令代码中不可能存在符号 所以只有重定位表,等表格,才是符号能够存在的位置, 代码内部,不存在什么符号的。 除非有 DLL调用,虚函数等存在, 编译器一般直接生成 call 指令。 obj 的链接实际上是要整合重定位表的。 如果没有 DLL调用,无论多少obj 链接到一起, 和单个obj生成的代码,没有多少区别。
flying_music 2015-12-01
  • 打赏
  • 举报
回复
这是个比较复杂的问题,要直接解决的话可以将String的实现也放到String的头文件中,具体原因可以参考这篇文章 http://wenku.baidu.com/link?url=mvpxSGFaMHwZddH54lvf6WvWL-BtGC4syV7OCwO42GLrtz9_bhYO84XztTaimoU_xjmg1n2UVSVjgr7XgmgSlcA8YtU84dj3-cLrGuwR5_3

64,654

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧