关于类模板编译的问题

lc19890326 2008-04-09 10:49:59
先看下面的代码

#ifndef MEDIAN_H
#define MEDIAN_H
#include<iostream>
#include<algorithm>
using namespace std;
template <typename T>
bool median(const vector<T>&,T&);// 错误1
#include"median.cpp"
#endif

这是median.hpp文件


#include"median.hpp"
#include<vector>
#include<algorithm>
template <typename T>
bool median(const vector<T>& c,T& m)
{
vector<T> temp(c);
if(temp.size()%2==0)
return false;
sort(temp.begin(),temp.end());
vector<T>::size_type index=temp.size()/2;
if(temp[index]>temp[index-1]&&temp[index]<temp[index+1])
{
m=temp[index];
return true;
}
else
return false;
}// 错误2

这是median.cpp文件


#include<iostream>
#include"median.hpp"
#include"median.cpp"
#include<vector>
using namespace std;
int main()
{
int ia1[]={1,2,3,4,5,6,7};
int ia2[]={1,2,3,4};
int ia3[]={1,2,2,3,4,5,6};
vector<int> ivec1(ia1,ia1+7);
vector<int> ivec2(ia2,ia2+4);
vector<int> ivec3(ia3,ia3+7);
int m;
if(median(ivec1,m))
cout<<"median: "<<m<<endl;
else
cout<<"no median"<<endl;
if(median(ivec2,m))
cout<<"median :"<<m<<endl;
else
cout<<"no median"<<endl;
if(median(ivec3,m))
cout<<"median: "<<m<<endl;
else
cout<<"no median"<<endl;
return 0;
}

这是主文件
用VS2005编译的时候出现错误
error C4430: 缺少类型说明符 - 假定为 int。注意: C++ 不支持默认 int
error C2143: 语法错误 : 缺少“,”(在“<”的前面)
这两个错误出现在错误1处
error C2995: “bool median(const std::vector<T> &,T &)”: 函数模板已经定义
这个错误在错误2

请问问题出在哪里

还有个问题,请解释下median.hpp中那个#ifndef #endif预编译有什么作用呢?

请高手赐教
...全文
193 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
great-sage 2008-12-18
  • 打赏
  • 举报
回复
看C++ templates吧,里面对这个问题讨论得很详细。
包含编译模型就是类模板的声明和定义放在一个头文件里
分离模型就是和将声明与实现分开
不过要用到export关键字
===================================

这个帖子已经很久了,我也在这几天看到这本书的这一段内容,发现书中所说的"包含"编译模型并不是说
将声明和定义放在一个头文件时.

书中说:
标准C++为编译模板定义了两种模型:包含模型和分别模型,这两种方式很大程度上是相同的:类定义和函数声明
放在头文件中,而函数定义和成员定义放在源文件中.这两种模型不同之处在于,编译器怎样使用来自源文件的定义而已.

对"包含编译模型",可以通过在声明函数模板或类模板的头文件中添加一条#include指示使定义可用,
从而引入包含相关定义的源文件.如下:

---------------------
// header file utlities.h
#ifndef AAAA_H
#define AAAA_H
template <class T> int compare(const T&, const T&);
......
#include "utilities.cc"
#endif

=======---------------
//implementation file utlities.cc
template <class T> int compare(const T &v1,const T &v2)
{
//implemente
......
}
-------------------

这一策略使我们能够保持头文件和实现文件分离.

本书的作者并不是说"包含编译模型"就是将申明和定义放在同一个头文件中.这里分别放在了utlities.h和utlities.cc中,
只是在utlities.h时用了#include "utlities.cc".

而"分离编译模型"只是在使用了关键字"export"来告诉编译器模板定义在哪里引用.
如果在头文件类声明中使用了export,则该头文件只能被源文件使用一次;
如果在实现文件中使用了export,有两种情况:

一种是在实现文件的开头加上
export template <class Type> class Xxxx;
#include "Xxxx.h"
//others definitions
....

这类情况中,导出类成员都会自动声明为导出.
另一种情况就是对个别成员声明要导出的,只能对个别成员使用export.


"包含编译模型"并不是类模板的声明和定义放在一个头文件里;
"分离编译模型"也并不是将申明和定义分开.

bbshliu 2008-04-10
  • 打赏
  • 举报
回复
偶的神啊,我也为这个问题困扰两三天了,不懂究竟为什么要这样,微软岂不是把实现代码都公开了
不知道gcc是不是也要这样
jinwei1984 2008-04-10
  • 打赏
  • 举报
回复
楼上很强~~~
hastings 2008-04-10
  • 打赏
  • 举报
回复
这个问题学到模板时,几乎每人必问,当初我也问过这个问题.
且是我在CSDN发的第一个帖.
ttkk_2007 2008-04-10
  • 打赏
  • 举报
回复
额 那C++ primer 上面写的包含编译模型和分别编译模型两种是指什么呢?

另外 我就不懂头文件里面#ifndef有什么作用
==================================================
现在编译器一般都不支持分离模式,书上只是说有这种模式

#ifndef防止头文件重复包含
Chappell 2008-04-10
  • 打赏
  • 举报
回复
intel的编译器可以把模板分别放在.h 和 .cpp文件中编译
Chappell 2008-04-10
  • 打赏
  • 举报
回复
z_kris 2008-04-10
  • 打赏
  • 举报
回复
再补充一下,分离编译模型是理论上的一个很好的模型
但是对编译器厂商要求比较高,目前只有一个编译器能比较好的实现分离编译功能
目前来说还是用置入式模型吧
z_kris 2008-04-10
  • 打赏
  • 举报
回复
那C++ primer 上面写的包含编译模型和分别编译模型两种是指什么呢?

看C++ templates吧,里面对这个问题讨论得很详细。
包含编译模型就是类模板的声明和定义放在一个头文件里
分离模型就是和将声明与实现分开
不过要用到export关键字

#ifndef是防止重复包含 google一下吧
lc19890326 2008-04-10
  • 打赏
  • 举报
回复
额 那C++ primer 上面写的包含编译模型和分别编译模型两种是指什么呢?

另外 我就不懂头文件里面#ifndef有什么作用
Supper_Jerry 2008-04-10
  • 打赏
  • 举报
回复
目前的编译器都不支持定义和实现分离
baihacker 2008-04-09
  • 打赏
  • 举报
回复
------ 已启动生成: 项目: Console, 配置: Debug Win32 ------
正在编译...
Console.cpp
median.cpp
正在生成代码...
正在链接...
正在嵌入清单...
生成日志保存在“file://d:\工程区\VS.NET工程区(9)\Console\Console\Debug\BuildLog.htm”
Console - 0 个错误,0 个警告
========== 生成: 成功 1 个,失败 0 个,最新 0 个,跳过 0 个 ==========
baihacker 2008-04-09
  • 打赏
  • 举报
回复

//模板不要分开
#ifndef MEDIAN_H
#define MEDIAN_H
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
template <typename T>
bool median(const vector<T>& c,T& m)
{
vector<T> temp(c);
if(temp.size()%2==0)
return false;
sort(temp.begin(),temp.end());
vector<T>::size_type index=temp.size()/2;
if(temp[index]>temp[index-1]&&temp[index]<temp[index+1])
{
m=temp[index];
return true;
}
else
return false;
}// 错误2

#include"median.cpp"
#endif

HelloDan 2008-04-09
  • 打赏
  • 举报
回复
类模板的不要分开文件,就在一个里面才行的。大部分编译器都是这样的。

64,646

社区成员

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

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