在哪里可以找到一个没有风险的防控金融风险网站呢?

1.声明部分
#ifndef _POINT_
#define _POINT_
template&class Elem& class Point
Point(Elem);
2.实现部分
//point.cpp
#include &point.h&
#include &iostream&
template&class Elem& Point&Elem&::Point(Elem e)
cout && e &&
3.主程序部分
//main.cpp
#include &point.h&
//出错的地方
#include &iostream&
void main()
Point&int& p(10);
编译的时候出现错误:
mainTest.obj : error LNK2019: 无法解析的外部符号 &public: __thiscall Point&int&::Point&int&(int)& (??0?$Point@H@@QAE@H@Z),该符号在函数 _main 中被引用
F:\C++Test\templateTest\Debug\templateTest.exe : fatal error LNK1120: 1 个无法解析的外部命令
4.解决办法
将main.cpp中的#include &point.h& 修改为 #include &point.cpp&
a)C++中模板的声明和实现能分离,只是在主程序中#include的是相应的.cpp
b)C++中模板的声明和实现最好不要分开,都写在.h文件,这是因为在多个cpp文件中引用模板参数时可能引起重复定义的编译错误
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:2459次
排名:千里之外
(2)(1)(1)(1)(1)(1)(3)  最近在改一个C++程序的时候碰到一条警告信息,警告信息为:&
& & & & & & & & 删除指向不完整&Q2DTorusNode&类型的指针;没有调用析构函数& & & & & & & & 1&
c:\users\lxw\desktop\dragonfly第二阶段实验\最终的实验版本\实验目录\dragonfly_modify\src\Q2DTorus.h(6) : 参见&Q2DTorusNode&的声明
& & & 警告信息很是奇怪,其实出于强迫症的原因想要解决掉这个警告信息,而且从警告信息来看,程序也应该存在内存泄露的问题,因为警告直接明白告诉你了,没有调用析构函数,接下来就是我解决的过程。我会搭建一个简单的程序来模拟这个错误,因为程序是在有些多~
& & & 警告的来源:
& & & 一个头文件A.h包含class A的代码如下:&&
#ifndef AH
#define AH
  一个头文件B.h包含class B的代码如下:
#ifndef BH
#define BH
  & &此时编译就会产生类似上面的警告信息:warning C4150: 删除指向不完整&B&类型的指针;没有调用析构函数。
& & &原因分析:
& & &  &因为class A中B的声明依赖于class B的前置声明,而不是#include "B.H",所以B的定义对A来说不可见,所以无法调用析构函数,导致内存泄露。
& & 程序的变化
& & 此时如果class A和class B相互保持对方类型的成员会如何呢?
& & & & A.h的代码:
#ifndef AH
#define AH
   B.h的代码:
#ifndef BH
#define BH
#include "A.h"
  这段代码存在问题,因为如果静态定义对象A,B,此时必定存在一个对象的定义对于另外一个对象的定义不可见,所以定义失败。如果均是利用#include对方,取决于编译器的顺序必定一个定义不可见。然而前置声明不能定义对象。
& & 解决方案:
& & &&此种状况的解决利用前置声明定义的那个类中的保持另外一个类的引用定义为指针,定义指针时不需要对那个类的定义可见。
& & 另外的问题:
#ifndef AH
#define AH
void setB() {
b-&haha();
#ifndef BH
#define BH
#include "A.h"
void haha() {
& & & 但是利用前置声明导致定义指针成员的类会出现最开始说的warning警告,因为定义不可见的原因。
& & & & & & & &&warning C4150: 删除指向不完整&B&类型的指针;没有调用析构函数&
& & & 而且另外的一个问题是在该.h文件中不能使用该指针调用这个类的成员,原因也是定义不可见。
& & & & & & & &&error C2227: &-&haha&的左边必须指向类/结构/联合/泛型类型&
& & 解决方案:
& & & 此时需要将A.h的所有成员函数实现重新定义一个.cpp文件,然后该.cpp文件去#include 指针成员类的头文件声明,此时定义可见,即可定义析构函数,调用指针的类成员了。
#ifndef AH
#define AH
void setB();
#ifndef BH
#define BH
#include "A.h"
void haha() {
#include "A.h"
#include "B.h"
void A::setB() {
b-&haha();
& & &问题到此就解决完毕了~
阅读(...) 评论()C++中声明和实现的分离的必要性(以及头文件的必要性)
我们经常在C++编程的时候使用这种模式,主要包括类的声明、方法的声明与他们各自的实现。大部分的书籍告诉你,这种模式的编程方法,会让程序变得很清晰易读,但我认为,但是这种编程模式的出现绝不只是由于这个原因,还有一些,如果不用这种分离就没有办法实现的情况。
我们说过,C++编程最经典的方法,就是,在头文件中放类的框架(包括变量和方法的声明),然后,使用该类的文件要include它,实现该类的文件也要include它。两个文件各自在头文件的帮助下,独立编译成功,下一步就是链接工作。链接工作是以main函数为起点,找到那些许多函数的实现文件(通过头文件中的类定义,或者是方法的定义接口,因为在定义文件中他们也会有这方面的定义)。
这种典型的实现中,包括两个方面的技术:一,使用头文件;二声明是实现分离。
头文件的正真作用,是很难一两句话说清楚的;不过你可以想象一下没有头文件的什么样子,对!所有你需要将某个文件内容编译成功,所要涉及的代码你都需要在该文件中有一份。其中,如果有一个共用类(或着共用方法),就需要你在每个需要使用该类该方法的文件中显示赋值一份他们的code(至少是声明框架),这种编程是绝对不容许的,它让程序员抓狂,让代码编程一团乱麻;或者你还有一种选择,那就是将所有的code都放在一个文件中,这样所有的类、方法的声明定义只需要一份就行了。但是这种程序你是编不大的!
头文件的作用,是使用引入文件的方式来代替那种直接需要程序员写重复代码的缺点,虽然实质上,include仍然是copy代码!在这样会让程序变得很清晰、管理条理。
从上面的分析我们可以看出,最疯狂的程序员,可以避开使用include头文件。因为基本上头文件的功能只是让各个文件方便的共用(copy)某些文件(用于编译成功)。但是绝对没有人真的会这么建议你这样开发C++程序。
倒是有一东西程序员无法避免,那就是声明与实现的分离。
我们在来分析一下,声明和实现的分割线在哪里,也就是说,定义一个东西(类、方法),那些code是声明、哪些code是实现。事实上,他们的分割线在于编译器的功能。
为什么成为声明,为什么,那就是要告诉编译器,我虽然没有将完整的定义code,写在这里,但是我告诉你我将有一个这样的完整定义,并且我告诉你,你(编译器)编译的时候所需要的全部内容。
这就是我们要说的,编译器编译程序的时候所需要的内容并不是实现的那部分,而是需要声明的那部分,也就是说:
对于变量,我需要知道它的类型,它的内容对我来说没用;
对于方法,我需要知道它的类型,包括参数列表和放回值;
对于类,我需要知道它的框架,包括对变量和方法的声明;
(注意,定义类的普通成员变量和函数时,变量只是声明,不是定义,因为程序就算运行到这个类也不会去定义,这个声明只是为了将来实例对象进行定义的。方法就不用说了,所以C++才鼓励你把函数的实现放在其他地方,因为那样函数和变量就同等关系了)
也就是说,因为编译器顺序扫描源文件,所以,在编译到使用了某个函数或者类的时候,一定需要知道他们框架,也就是前面我们所说的。根据这些信息编译器就能做所有它要做的事情。也是因为这个原因,我们才能在未正式定义某个函数(类)之前可以在编程的时候使用它,因为我们声明了它,我们告诉了编译器有一个这样的东西,所以别害怕。编译完成,进行链接的时候,就是证明你说的是不是真的时候,如果连接器找不到你前面说过有的东西,就报错。到最后运行的时候,所有的东西都是记录在册(名字表)的,没有所谓的前后关系,所以当程序使用了某个函数(要运行里面的代码),就算该函数的代码在这个调用语句后面也没有关系,因为这些记录都以及记录在册了!
好了!我们说了,申明和实现的好处,那么,我为什么不能将那些定义直接放在它被调用的语句的前面呢?对!这也是我们经常干的事情,但是有时候你没有办法这么做。
(1)当函数a要用到函数b,函数b又要用到函数a。
(2)当类A对象要用到类B对象,类B对象又要用到类A对象。
或许你觉得这种编程模式实在是太奇怪了,你不用觉得奇怪,但的确存在这种情况。这个时候你将那个定义放在前面都会出错。所以,解决的方法就是,将他们的两个申明放在都放在前面,然后再后面逐个实现各自的实现。
因为声明是不会涉及到细节的:
函数的声明只包括类型和函数名,如果不设计到实现的化,两个函数的声明是不会干扰对方的(从申明那里看不到他们两个要相互调用);当到了函数实现的时候,因为前面已经有了两个函数的申明,所以使用的时候可以编译成功,(因为编译只在乎函数的头部,就是申明时所使用的),不管在此之前该函数的实现过程是否出现。
再看看类的声明,如果A类的框架申明使用了B类的东西。有几种使用模式:
1)直接使用B类类型作为变量类型、参数类型、返回类型。这个使用A类最简单的声明就可以了(不用框架)。
2)使用B类中的成员(数据、方法)。这个时候,你就必须要将B类的结构(框架:包括那些数据和方法成员)放在前面。这就是类框架声明,如果只使用类最简单的申明,那编译器根本就不知道该类含有什么。
3)使用B类中的类型。使用方法,自然是B类名::类型名。这也需要知道B类的结构。
同理,B类也有可能使用上面三种方式来使用A类。于是如果不使用声明和实现分离,就没有办法成功的定义这两个类,因为大家都以对方为依托。但是使用声明和实现分离你会发现,就声明本身只会涉及到对另外一个类应用的框架的使用。
但是声明与实现的分离也并不是万能的。
相互使用类型的时候,可以先在最上面使用两个类声明:
这样,在下面的A与B的框架声明使用对方类型就可以吗?实验证明不可以,报类性定义不完全,前面我们提到过这种错误,因为当B的类框架不完整出现的话,编译器没有办法知道它的大小,所以这个时候只能使用他们的引用或指针。
如果需要使用对方的对象成员,那其实在类框架声明中不会涉及到函数成员的实现,所以,要对对方成员的使用在类框架声明的时候是可以避免的。
倒是有一样东西很难做,那就是类的内部类型的使用。因为这个东西在声明的时候就要使用。没有办法像使用对方成员那样可以避免。也没有所谓的使用
B::Bc;这样的语句好像是在告诉你我将来在B中有一个Bc类型。但是这个声明是无效的。
实验代码如下:
class A;& //这个其实没有什么用!
class B::Bc;&
//无效,该并不能告诉编译器你想告诉的东西,并且报错,说Bc没有在B中定义。
//对对方类的使用——这里只能使用指针,否则报B类型没有完整定义的错误。
//对对方类中类的使用;&&
——这里报错说Bc没有在B中定义。
int fun();
//对对方类的使用,这里使用就没有是,因为A的框架已经完整
//对对方类中类的使用;& 这里的使用也没有事。
int fun();
int A::fun()
&& b.fun();//对对方成员的使用
cout&&b.b;
int B::fun()
& a.fun();
& cout&&a.a;
其实,从上面我们可以总结出一些东西来!
(1)头文件机制虽然理论上讲可以避免使用,但是基本不太实际,这样不可能编出有规模的C++程序
(2)声明与实现分离,是一个很重要的机制,很多时候,编程是不能避免的。
&(3)就算使用了声明与实现分离技术,也并不是所有的事情都能合理完成,就像前面的你不能直接定义只总是在前面做了简单声明的类的对象,因为编译器不知到该类的结构,这成为不完全定义,只能定义它的引用和接口。更糟糕的是,因为没有办法简单声明在类中类的存在,所以无法使用该类中的类(在没有类框架之前使用)。
(4)最后的编程方法就是大量使用头文件机制,并且在头文件中,尽量值包含相关对象的申明(虽然实现可以放在里面)。头文件就像是一个共用的标准模板(也可以说成接口吧)一样。还是那句话,使用该类的人只需要include该类的最简单的框架(这就是接口,这个接口统一了,不同文件对统一个类的使用,因为如果你不使用include你可以自行定义)。定义该类的文件include该类框架之后,给出该类的具体实现。并编译成目标文件。
这样,主体文件编译后成为目标文件,然后通过链接寻找目标文件。这个时候就涉及到了是动态链接和静态链接了。不过初步认为,属于动态链接(它的优势显而易见)。
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。为什么不能将类模板的声明与类模板函数实现分开写
定义一个类一般都是在头文件中进行类声明,在cpp文件中实现,但使用模板时应注意目前的C++编译器还无法分离编译,最好将实现代码和声明代码均放在头
文件中。如:
template &class T&
class CTest
public: & & &
& T& GetValue();
& void SetValue(const T&
protected:
template &class T&
CTest&T&::GetValue()
&& return m_V
template&class T&
void CTest&T&::SetValue(const
T& _Value)
&& m_Value & =
在这儿test.cpp中的内容应放在test.h中,否则在生成最终可执行程序时就会出现错误(在链接时会出错)。因为在编译时模板并不能生成真正的二进制代码,而是在编译调用模板类或函数的CPP文件时才会去找对应的模板声明和实现,在这种情况下编译器是不知道实现模板类或函数的CPP文件的存在,所以它只能找到模板类或函数的声明而找不到实现,而只好创建一个符号寄希望于链接程序找地址。但模板类或函数的实现并不能被编译成二进制代码,结果链接程序找不到地址只好报错了。
《C++编程思想》第15章(第300页)说明了原因:
模板定义很特殊。由template&…&
处理的任何东西都意味着编译器在当时不为它分配存储空间,它一直处于等待状态直到被一个模板实例告知。在编译器和连接器的某一处,有一机制能去掉指定模板的多重定义。所以为了容易使用,几乎总是在头文件中放置全部的模板声明和定义。
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

我要回帖

更多关于 防范金融风险 的文章

 

随机推荐