[提问C++ Primer - Chapter 2] Unresolved external ? 使用类模板时的编译错误
偶最近刚刚开始看 C++ Primer, 但第二章中的Array<elemType>便调不通了。
偶使用的例子是 jjhou 网站上的cpp-primer-code/chapter2/Array.h 及 Array.cpp
编译的一条错误内容如下:
[Linker Error] Unresolved external 'Array<int>::grow()' referenced from F:\CPPPRIMER\UNIT1.OBJ
偶的编译器是 BCB6.0, 不过偶在VC6.0试了一下, 也是同样的错误。
大虾帮帮忙。。。thx
问题点数:50、回复次数:11Top
1 楼standlove(阿基米德)回复于 2002-11-25 00:51:43 得分 0
偶第一次在这里问问题, 不知道有没有问错地方?
另:
其他错误内容与上面的内容差不多,只是函数不一样而已。
以后可能还会遇到n多问题,希望大家有空的时候不要忘了瞧一下偶的
[提问C++ Primer - Chapter n]
不胜感激!Top
2 楼merlinran(天行者)回复于 2002-11-25 12:17:04 得分 0
UNIT1.OBJ?你有什么文件叫做unit1吗?最好把原文件全部贴出来。不是每一个人都有你所说的那本书,也不会有你所说的例子。Top
3 楼standlove(阿基米德)回复于 2002-11-25 18:46:01 得分 0
原文件如下: 有些长了,不知道大虾会不会没有耐心 -_-
Array.h
#ifndef ARRAY_H
#define ARRAY_H
#include <iostream.h>
template <class elemType> class Array;
template <class elemType> ostream&
operator<<(ostream &, Array<elemType> &);
template <class elemType>
class Array {
public:
// explicit Array(int sz = DefaultArraySize);
Array(int sz = DefaultArraySize)
{ init(0, sz); }
Array(const elemType *ar, int sz)
{ init(ar, sz); }
Array(const Array &iA)
{ init(iA._ia, iA._size); }
virtual ~Array() { delete[] _ia; }
Array& operator=(const Array&);
int size() const { return _size; }
virtual elemType& operator[](int ix) { return _ia[ix]; }
virtual elemType operator[](int ix) const { return _ia[ix]; }
elemType at(int ix) const { return _ia[ix]; }
virtual ostream &print(ostream& os = cout) const;
virtual void grow();
virtual void sort(int, int);
virtual int find(const elemType &);
virtual elemType min();
virtual elemType max();
protected:
void init(const elemType*, int);
void swap(int, int);
// static const int DefaultArraySize = 12;
static const int DefaultArraySize;
int _size;
elemType *_ia;
};
#endif // ARRAY_H
///////////////////////////////////////////////////////////////
Array.cpp
#ifndef ARRAY_CPP
#define ARRAY_CPP
#include "Array.h"
#include <assert.h>
template <class elemType>
const int Array<elemType>::DefaultArraySize = 12;
template <class elemType>
void Array<elemType>::init(const elemType *array, int sz)
{
if (!array) { _size = 0; _ia = 0; }
if (sz < 1) sz = 1;
_size = sz;
_ia = new elemType[_size];
for (int ix = 0; ix < _size; ++ix)
if (!array)
_ia[ix] = 0;
else
_ia[ix] = array[ix];
}
template <class elemType> Array<elemType>&
Array<elemType>::operator=(const Array<elemType>& iA)
{
if (this == &iA)
return *this;
delete[] _ia;
init(iA._ia, iA._size);
return *this;
}
template <class elemType> ostream&
operator<<(ostream &os, Array<elemType> &ar)
{
return ar.print(os);
}
template <class elemType>
ostream& Array<elemType>::print(ostream &os) const
{
const int lineLength = 12;
os << "( " << _size << " )< ";
for (int ix = 0; ix < _size; ++ix)
{
if (ix%lineLength == 0 && ix)
os << "\n\t";
os << _ia[ix];
// don't generate comma for last item on line
// nor for the last element of the array
if (ix%lineLength != lineLength-1 && ix != _size-1)
os << ", ";
}
}
template <class elemType>
void Array<elemType>::grow()
{
elemType *oldia = ia;
int oldSize = _size;
_size = oldSize + oldSize/2 + 1;
_ia = new elemType[_size];
int ix;
for (ix = 0; ix < oldSize; ++ix)
_ia[ix] = oldia[ix];
for ( ; ix < _size; ++ix)
_ia[ix] = 0;
delete[] oldia;
}
template <class elemType>
elemType Array<elemType>::min()
{
elemType min_val = _ia[0];
for (int ix = 1; ix < _size; ++ix)
if (min_val > _ia[ix])
min_val = _ia[ix];
return min_val;
}
template <class elemType>
elemType Array<elemType>::max()
{
elemType max_val = _ia[0];
for (int ix = 0; ix < _size; ++ix)
if (max_val < _ia[ix])
max_val = _ia[ix];
return max_val;
}
template <class elemType>
int Array<elemType>::find(const elemType& val)
{
for (int ix = 0; ix < _size; ++ix)
if (_ia[ix] == val)
return ix;
return -1;
}
template <class elemType>
void Array<elemType>::swap(int i, int j)
{
elemType tmp = _ia[i];
_ia[i] = _ia[j];
_ia[j] = tmp;
}
template <class elemType>
void Array<elemType>::sort(int low, int high)
{
if (low >= high) return;
int lo = high;
int hi = high + 1;
elemType elem = _ia[low];
for ( ;; ) {
while (_ia[++lo] < elem) ;
while (_ia[--hi] > elem) ;
if (lo < hi)
swap(lo, hi);
else break;
}
swap(low, hi);
sort(low, hi-1);
sort(hi+1, high);
}
#endif // ARRAY_CPP
////////////////////////////////////////////////////////////////
Unit1.cpp
// #include <iostream>
#include <iostream.h>
#include "Array.h"
/**
**
[ 0 ] ia: 0 ca: a da: 0
[ 1 ] ia: 1 ca: b da: 1.75
[ 2 ] ia: 2 ca: c da: 3.5
[ 3 ] ia: 3 ca: d da: 5.25
**
**/
int main()
{
const int array_size = 4;
// elemType becomes int
Array<int> ia(array_size);
// elemType becomes double
Array<double> da(array_size);
// elemType becomes char
Array<char> ca(array_size);
int ix;
for ( ix = 0; ix < array_size; ++ix ) {
ia[ix] = ix;
da[ix] = ix * 1.75;
ca[ix] = ix + 'a';
}
for ( ix = 0; ix < array_size; ++ix )
cout << "[ " << ix << " ] ia: " << ia[ix]
<< "\tca: " << ca[ix]
<< "\tda: " << da[ix] << endl;
return 0;
}
Top
4 楼standlove(阿基米德)回复于 2002-11-25 18:48:16 得分 0
其中 Array.h 与 Array.cpp 是类文件(废话),Unit1.cpp 是主文件。
属于 command line 的编译环境。
Top
5 楼warrior(不断领悟)回复于 2002-11-25 19:17:08 得分 0
链接时指定了Array.obj文件了吗?
这不是编译错误,是链接错误,建议你使用IDE创建一个项目来管理这些文件,这样IDE会自动处理项目中这些文件之间的依赖关系。
要不然要在命令行指定链接时用到的目标(OBJ)文件,查查命令行的帮助吧。Top
6 楼standlove(阿基米德)回复于 2002-11-25 19:43:37 得分 0
不好意思, 偶用的编译器是BCB6.0,是dos界面的 --- command line!
所有文件确实是放在一个工程里的!
该不会是BCB6.0的工程问题吧。。。Top
7 楼standlove(阿基米德)回复于 2002-11-25 19:45:50 得分 0
更正:程序是dos界面的。
最近有点累了。。。。老是想错字Top
8 楼ashchan(幻大灰 - ashchan.com)回复于 2002-11-25 21:45:39 得分 10
同意 warrior ,建一个工程,并把所有用到的头文件和实现文件加入到该工程。Top
9 楼merlinran(天行者)回复于 2002-11-25 22:05:15 得分 40
哦,明白了。你可以把Array.cpp的内容全部移到Array.h内容的后面,然后再编译执行。标准可以支持把模板类的实现放在单独的文件中,但具体的编译器不一定支持。Top
10 楼standlove(阿基米德)回复于 2002-11-25 23:30:53 得分 0
thx
问题已经解决。 但为什么啊, 偶用的可是BCB6.0最新的编译器啊!
Top
11 楼zeey(zeey)回复于 2002-12-01 14:49:06 得分 0
套用一下以前别人说过的话,hoho,不好意思啦:
问题很简单,你把cpp文件的内容和并到.h文件中,因为你写的是模版类,本质上类似于宏,编译时是静态展开的,而不是先生成一个lib文件再去link,所以你include的头文件里必须包括类的声明,定义以及成员函数的声明、定义。不然编译器就认为你的函数只有声明没有定义,所以就出现以上的爆错信息。
Top




