posts - 3, comments - 0, trackbacks - 0, articles - 0
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

2012年5月25日

目前大部分的编译器都不支持C++模板类的声明与定义分离编译,因此模板类的声明和定义都要在同一个头文件中给出。
//----1.h-----//
#pragma once
template<typename _T>
class A
{
public:
   A():a(_T(0)),b(_T(0)){}
   A(_T ta,_T tb):a(ta),b(tb){}
   ~A(){}
public:
   const _T sum() constreturn a+b; };
private:
   _T a;
   _T b;
};
//顶层函数
template<typename _T>
A<_T> operator + (const A<_T> &al,const A<_T> &ar)
{
    A<_T> ta(al.sum(),ar.sum());
    return ta;
}
如果将声明放在1.h,定义放在1.cpp,如果按照正常的编程方式,在mian.cpp中加入#include "1.h",则编译会出现如下错误:
1>main.obj : error LNK2019: 无法解析的外部符号 "class A<int> __cdecl operator+<int>(class A<int> const &,class A<int> const &)" (??$?HH@@YA?AV?$A@H@@ABV0@0@Z),该符号在函数 _main 中被引用
1>E:\C++\test\Debug\test.exe : fatal error LNK1120: 1 个无法解析的外部命令
//-----------------分割线-------------------//
如果在1.h头文件中出现了非模板函数,譬如说
//-------1.h---------//
A<doubleoperator + (const A<double> &al,const A<int> &ar)
{
    A<double> ta(al.sum(),(double)(ar.sum()));
    return ta;
}
那么这个非模板函数最好声明和定义分离,即将非模板函数定义写在1.cpp中,否则在多个CPP文件同时包含1.cpp时会出现LN2005错误:
1>1.obj : error LNK2005: "class A<double> __cdecl operator+(class A<double> const &,class A<int> const &)" (??H@YA?AV?$A@N@@ABV0@ABV?$A@H@@@Z) 已经在 main.obj 中定义
1>E:\C++\test\Debug\test.exe : fatal error LNK1169: 找到一个或多个多重定义的符号
//-----------------分割线------------------//
总结:模板类的声明和定义在同一个头文件中,非模板类或函数的声明和定义分别写在头文件和cpp文件中。

posted @ 2012-05-25 13:40 赵氏呱呱儿 阅读(835) | 评论 (0)编辑 收藏

2012年5月18日

版本:CNL700/winms800i32
步骤1:打开VS2008,打开或新建一个项目
步骤2:项目 — 属性(弹出属性页)— 配置属性 — C/C++ — 常规 — 附加包含目录

添加:<VNI_DIR>\imsl\cnl700\<ENV>\include

步骤3:项目 — 属性(弹出属性页)— 配置属性 — C/C++ — 预处理器 — 预处理器定义
添加:IMSL_STATIC
步骤4:
项目 — 属性(弹出属性页)— 配置属性 — 链接器 — 常规 — 链接器依赖项
添加:<VNI_DIR>\imsl\cnl700\<ENV>\lib

步骤5:项目 — 属性(弹出属性页)— 配置属性 — 链接器 — 输入 — 附加依赖项
添加:
imslcmath_imsl.lib 
imslcstat_imsl.lib 
lmgr_md.lib 
libcrvs_md.lib
libsb_md.lib 
libFNPload.lib 
netapi32.lib 
advapi32.lib 
comctl32.lib 
wsock32.lib 
oldnames.lib 
步骤6:项目 — 属性(弹出属性页)— 配置属性 — 链接器 — 输入 —  忽略特定库
添加:libcmt.lib
步骤7:点击确定
 

 

 

 

posted @ 2012-05-18 17:23 赵氏呱呱儿 阅读(602) | 评论 (0)编辑 收藏

2010年11月10日

以前就发现了vector中的erase方法有些诡异(^_^),稍不注意,就会出错。今天又一次遇到了,就索性总结一下,尤其是在循环体中用erase时,由于vector.begin() 和vector.end()是变化的,因此就引入了错误的可能性。

vector<int> veci;
veci.push_back(1);
veci.push_back(2);
veci.push_back(3);
veci.push_back(4);
veci.push_back(5);
veci.push_back(3);
veci.push_back(2);
veci.push_back(3);

for(vector<int>::iterator iter=veci.begin(); iter!=veci.end(); iter++)
{
      if( *iter == 3)
             veci.erase(iter);
}

乍一看这段代码,很正常。其实这里面隐藏着一个很严重的错误:当veci.erase(iter)之后,iter就变成了一个野指针,对一个野指针进行 iter++ 是肯定会出错的。

查看MSDN,对于erase的返回值是这样描述的:An iterator that designates the first element remaining beyond any elements removed, or a pointer to the end of the vector if no such element exists,于是改代码:

for(vector<int>::iterator iter=veci.begin(); iter!=veci.end(); iter++)
{
      if( *iter == 3)
             iter = veci.erase(iter);
}

这段代码也是错误的:1)无法删除两个连续的"3"; 2)当3位于vector最后位置的时候,也会出错(在veci.end()上执行 ++ 操作)

正确的代码应该为:

for(vector<int>::iterator iter=veci.begin(); iter!=veci.end(); )
{
     if( *iter == 3)
          iter = veci.erase(iter);
      else
            iter ++ ;
}

posted @ 2010-11-10 22:01 赵氏呱呱儿 阅读(4622) | 评论 (0)编辑 收藏