没银行卡修改微信支付密码没设置过密码

1872人阅读
VC++ 基本概念与应用(101)
VC++(161)
C++学了这么多年你知道为什么定义类时,类的定义放在.h文件中,而类的实现放在cpp文件中。它们为什么能够关联到一起呢?你知道什么东西可以放在.h文件中,什么不能。什么东西又可以放在cpp文件中。如果你忘记了或是压根就不明白,那么读过此文你会清晰无比!!
首先谈下声明与定义的区别。
&&&&&&& 声明是将一个名称引入程序。定义提供了一个实体在程序中的唯一描述。声明和定义有时是同时存在的。
&&&&& extern int b=1;
&&& 只有当中不存在初始化式是才是声明。其他情况既是定义也是声明。
&&&& 但是在下列情况下,声明仅仅是声明:
&&&&&& 1:仅仅提供函数原型。如
&&&&&& 3:;
&&&&&& 4:声明
&&&&&& 5:在类中定义的静态数据成员的声明
&span style=&font-size: 18&&class A&{& && public:& &&& static int&};&/span&&
&span style=&font-size:18&&class A
&& 下列情况下 ,定义仅仅是定义:
&&&&& 1:在类定义之外,定义并初始化一个静态数据成员。如
&&&&& 2:在类外定义非内联成员函数。
&&&& 声明仅仅是将一个符号引入到一个作用域。而定义提供了一个实体在程序中的唯一描述。在一个给定的定义域中重复声明一个符号是可以的但是却不能重复定义否则将会引起编译错误。但是在类中的成员函数和静态数据成员却是例外,虽然在类内它们都是声明,但是也不能有多个。
&span style=&font-size: 18&&class A&{& &&& public:& &&&&& static int&&&&&& static int&&&&& void func(int ,int);&&&&& void func(int ,int);&};&/span&&
&span style=&font-size:18&&class A
void func(int ,int);
void func(int ,int);
&&&&&&& 明白了声明与定义的区别,还需要明白 内部链接、外部链接。只有明白了它们你才会知道开头提出的问题。
&&&&&& 在编译时,编译器只检测程序语法和函数、变量是否被声明。如果函数未被声明,编译器会给出一个警告,但可以生成目标文件。而在链接程序时,链接器会在所有的目标文件中找寻函数的实现。如果找不到,那到就会报链接错误码()。在下,这种错误一般是:错误,意思说是说,链接器未能找到函数的实现。
&&&&& 链接把不同编译单元产生的符号联系起来。有两种链接方式:内部链接和外部链接。
&&&&& 如果一个符号名对于它的编译单元来说是局部的,并且在链接时不可能与其他编译单元中的同样的名称相冲突,那个这个符号就是内部链接。内部链接意味着对此符号的访问仅限于当前的编译单元中,对其他编译单元都是不可见的。
&&&&&& static关键字作用在全局变量时,表示静态全局变量。但是作用域仅仅在当前文件作用域内。其他文件中即使使用声明也是无法使用的。也类似。
&&&&&& 带有、关键字和枚举类型的连接是内部的。
&&&&&& 具有内部链接的符号无法作用于当前文件外部,要让其影响程序的其他部分,可以将其放在文件中。此时在所有包含此文件的源文件都有自己的定义且互不影响。
&&&&&& 类的定义具有内部链接,由于它是定义,因此在同一编译单元中不能重复出现。如果需要在其他编译单元使用,类必须被定义在头文件且被其他文件包含。仅仅在其他文件中使用声明是不行的,原因就是类的定义是内部链接,不会在目标文件导出符号。也就不会被其他单元解析它们的未定义符号。理解这一点很重要。
&&&& 内联函数也具有内部链接。
&&&&& 在一个多文件的程序中,如果一个符号在链接时可以和其他编译单元交互,那么这个名称就有外部链接。外部链接意味着该定义不仅仅局限在单个编译单元中。它可以在文件中产生外部符号。可以被其他编译单元访问用来解析它们未定义的符号。因此它们在整个程序中必须是唯一的,否则将会导致重复定义。
&&&&&& 非内联成员函数、非内联函数、非静态自由函数都具有外部链接。
&&&&&& 内联函数之所有具有内部链接,因为编译器在可能的时候,会将所有 对函数的调用替换为函数体,不将任何符号写入文件。
&&&&&& 判断一个符号是内部链接还是外部链接的一个很好的方法就是看该符号是否被写入文件。
&&&&&& 前面说的是定义对链接方式的影响,接下来说下声明对链接方式的影响。
&&&&&& 由于声明只对当前编译单元有用,因此声明并不将任何东西写入文件。
&&&&&& int func();
&&&&&& 这些声明本身不会影响到文件的内容。每一个都只是命名一个外部符号,使当前的编译单元在需要的时候可以访问相应的全局定义。
&&&& 函数调用会导致一个未定义的符号被写入到文件。如果在该文件中没有被使用,那么没有被写入到文件。而函数有对此函数的调用。也就会将此符号写入目标文件。此后此文件与定义此符号的文件被连接在一起,前面未定义的符号被解析。
&&&& 上述声明有可能导致该符号被写入目标文件中。但是以下声明并不会导致该符号写入到目标文件中。
&span style=&font-size: 18&&typedefint Int;Class A;&
struct& union&/span&&
&span style=&font-size:18&&typedef int Int;Class A;
&&&& 它们的链接也是内部的。
&&&& 类声明和类定义都是内部链接。只是为当前编译单元所用。
&&&& 静态的类数据成员的定义具有外部链接。如
&span style=&font-size: 18&&class A&{& static& int&};&/span&&
&span style=&font-size:18&&class A
//声明。具有内部链接。
};&/span&
&&&&& 静态数据成员仅仅是一个声明,但是它的定义却具有外部链接。
&&&& C++对类和枚举类型的处理方式是不一样的。比如:在不定义类时可以声明一个类。但是不能未经定义就声明一个枚举类型。
&&&& 基于以上的分析,我们可以知道:将具有外部链接的定义放在头文件中几乎都是编程错误。因为如果该头文件中被多个源文件包含,那么就会存在多个定义,链接时就会出错。
&&&& 在头文件中放置内部链接的定义却是合法的,但不推荐使用的。因为头文件被包含到多个源文件中时,不仅仅会污染全局命名空间,而且会在每个编译单元中有自己的实体存在。大量消耗内存空间,还会影响机器性能。
&&&& const和修饰的全局变量仅仅在当前文件作用域内有效。它们具有内部链接属性。
&&& 下面列出一些应该或是不应该写入头文件的定义:
&span style=&font-size: 18&&&#ifndef TEST_H& #define TEST_H&
int&&&& &extern int b=10;&const int c=2;&static int d=3;&static void func(){}&
void func2(){} &void func3();&class A& {& && public:& &&&& static int&&&&& int f;&&&&& void func4();&};& A::e=10;&void A:func4()&{& & & }& #endif&/span&&
&span style=&font-size:18&&//test.h
#ifndef TEST_H
#define TEST_H
//a有外部链接,不能在头文件中定义。
extern int b=10;//同上。
const int c=2;//c具有内部链接,可以定在头文件中但应该避免。
static int d=3;//同上。
static void func(){} //同上。
void func2(){} //同a。
void func3();//可以。仅仅是声明。并不会导致符号名被写入目标文件。
//可以,具有内部链接。
int f;//可以,同上。
void func4();//声明,内部链接。同上。
A::e=10;//不可以在头文件中包含具有外部链接的定义。符号名别写入目标文件。
void A:func4()//不可以,类成员函数。外部连接。
#endif&/span&
&&&&& 相信大家现在明白为什么只在类型声明成员函数,而不实现它是合法的了。也可以回答为什么类的定义可以放在文件中。而类的实现可以放在同名的文件中。老师以前的介绍是说编译器会自动寻找同名的文件。其实是因为由于文件中存储的是成员函数的实现,而成员函数具有外部链接特性,会在目标文件产生符号。在此文件中此符号是定义过的。其他调用此成员函数的目标文件也会产生一个未定的符号。两目标文件连接后此符号就被解析。注意数据成员应该放在文件中。而不能放在文件。
&&&&& 有内部链接的定义可以定义在文件中,并不会影响全局的符号空间 。但是在文件作用域中要避免定义(并不禁止)没有声明为静态的数据和函数,因为它们具有外部链接。
&span style=&font-size: 18&&int&
void func()& {&&& && ......& }&/span&&
&span style=&font-size:18&&
void func()
&&&&& 上述定义具有外部链接可能会与全局命名空间的其他符号名称存在潜在冲突。如果确实需要使用全局的变量或函数。可以为它们加上static关键字。使其作用域局限在当前文件内,具有内部链接也就不会对全局命名空间产生影响。因为内联函数和静态自由函数、枚举以及类型的数据都具有内部链接,所以它们可以定义在文件中,而不会影响全局命名空间。
&&&&& typedef和宏定义不会将符号引入文件,它们也可以出现在文件中,不会影响全局命名空间。
&&&&& typedef 为一个已存在的类型创建一个别名。而不是创建一个新的类型。它不提供类型安全。如
&span style=&font-size: 18&&typedefint IntA;&
typedef int InB;&/span&&
&span style=&font-size:18&&typedef int IntA;
typedef int InB;&/span&
&&&&&& 在需要的地方使用是不会报错的。它们可以互相替换。因为此我们称它不提供类型安全。但是在定义函数类型时经常使用,可以使定义更清晰。
&&&&& 标准库提供一个宏,用以保证给定的表达式值非零。否则便会输出错误信息并终止程序执行。只有在程序中没有定义时,才会工作。一旦定义,语句将会被忽略
。注意与中的相区别。是提供的。当被定义时才会起作用。
在的模式下会被定义。而在模式下会被定义。
&&& 好了,相信大家都会明白开头提出的问题了。如果有不明白的,请务必留言哦。如有错误,也请不吝指正!!
&&& 以上内容参考自《Large Scale C++ software design》。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:653672次
积分:9390
积分:9390
排名:第1520名
原创:208篇
转载:587篇
评论:59条头文件中只能有声明,不能放定义
一般模板可以放在多个点h文件中,声明可以放在点h文件中
但是定义却不可以放在点h文件中,而必须单独放在点CPP文件中
首先必须了解编译的过程,编译的第一步是把所有的CPP文件编译成为点O文件,而且每一个点CPP文件都是单独编译的,该点CPP文件中用到的类型必须在它所include
的头文件当中找到,相当于把它所有include的文件中的代码都加到该CPP文件的前面,但是声明的部分将不会出现在编译后的点O文件,相当于每个CPP文件都是单独编译,因此它的ifndef在一个文件里是没有用的,两个CPP文件里如果包含同一个有ifndef的头文件,效果是两个CPP文件都把该头文件加到它的前面,但不会把声明的部分放到点O文件中,而会把头文件中定义的部分都输出到编译后的点O文件当中
因此如果在头文件当中有一个定义,那么如果有两个CPP文件当中include了它,那么将会出现重定义错误,multiple
definition of
由于模板不是真实的定义,所以可以放在头文件当中
声明作用只是在链接的时候进行查找,定位,如果出现对一个声明的两个定义,则会出错
********************************************
在下列声明和定义中 哪些应被放到头文件中 哪些应被放到程序文本文件中 为什么
(b) inline bool is_equal( const SmallInt &, const SmallInt & ) { }
(c) void putValues( int *arr, int size );
(d) const double pi = 3.1416;
(e) extern int total = 255;
附加问题:一般哪些声明跟定义应被放到头文件中 哪些应被放到程序文本文件中?
当设计头文件时,记住定义和声明的区别是很重要的。定义只可以出现一次,而声明则可以出现多次。下列语句是一些定义,所以不应该放在头文件里:
extern int ival = 10;
// initializer, so it's a definition
double fica_
// no extern, so it's a definition
虽然ival声明为extern,但是它有初始化式,代表这条语句是一个定义。类似地,fica_rate的声明虽然没有初始化式,但也是一个定义,因为没有关键字extern。同一个程序中有两个以上文件含有上述任一个定义都会导致多重定义链接错误。
因为头文件包含在多个源文件中,所以不应该含有变量或函数的定义。
对于头文件不应该含有定义这一规则,有三个例外。头文件可以定义类、值在编译时就已知道的const对象和inline函数。这些实体可在多个源文件中定义,只要每个源文件中的定义是相同的。
在头文件中定义这些实体,是因为编译器需要它们的定义(不只是声明)来产生代码。例如:为了产生能定义或使用类的对象的代码,编译器需要知道组成该类型的数据成员。同样还需要知道能够在这些对象上执行的操作。类定义提供所需要的信息。在头文件中定义const对象则需要更多的解释。
2. 一些const对象定义在头文件中
回想一下,const变量默认为定义该变量的文件的局部变量。正如我们现在所看到的,这种默认的原因在于允许const变量定义在头文件中。
在C++中,有些地方需要放置常量表达式。例如,枚举成员的初始化式必须是常量表达式。在以后的章节中将会看到其他需要常量表达式的例子。
一般来说,常量表达式是编译器在编译时就能够计算出结果的表达式。当const整型变量通过常量表达式自我初始化时,这个const整型变量就可能是常量表达式。而const变量要成为常量表达式,初始化式必须为编译器可见。为了能够让多个文件使用相同的常量值,const变量和它的初始化式必须是每个文件都可见的。而要使初始化式可见,一般都把这样的const变量定义在头文件中。那样的话,无论该const变量何时使用,编译器都能够看见其初始化式。
但是,C++中的任何变量都只能定义一次。定义会分配存储空间,而所有对该变量的使用都关联到同一存储空间。因为const对象默认为定义它的文件的局部变量,所以把它们的定义放在头文件中是合法的。
这种行为有一个很重要的含义:当我们在头文件中定义了const变量后,每个包含该头文件的源文件都有了自己的const变量,其名称和值都一样。
当该const变量是用常量表达式初始化时,可以保证所有的变量都有相同的值。但是在实践中,大部分的编译器在编译时都会用相应的常量表达式替换这些const变量的任何使用。所以,在实践中不会有任何存储空间用于存储用常量表达式初始化的const变量。
如果const变量不是用常量表达式初始化,那么它就不应该在头文件中定义。相反,和其他的变量一样,该const变量应该在一个源文件中定义并初始化。应在头文件中为它添加extern声明,以使其能被多个文件共享。
*************************************
内联函数为什么要放到头文件中
两个文件:
main.c中得代码如下
#include &stdio.h&
#include "print_inline.h"
int main(int argc, char *argv[])
print_inline();
system("PAUSE");&&&&
print_inline.h文件中得代码:
#include &stdio.h&
inline void print_inline()
&&&& printf("This is a inline function\n");&&&&&&&
在预处理得时候,会把main.c文件中得print_inline.h头文件展开,在DEVC下,预处理后的文件为main.i,(如果想要生成预处理后的文件,需要在工程属性里面,为编译器制定参数-c -save-temps&
)得到如下预处理后得结果(文件比较长,只取了最后的一部分):
# 3 "main.c" 2
# 1 "print_inline.h" 1
inline void print_inline()
&&&& printf("This is a inline function\n");
# 4 "main.c" 2
int main(int argc, char *argv[])
print_inline();
system("PAUSE");
很明显,在print_inline.h头文件中定义得函数print_inline()在main函数中被直接展开了,相当与我们把print_inline()函数的定义放在了main.c中,这样在编译的时候,编译器就可以把print_line()函数直接内联到main函数中
但是如果我们把print_inline()函数的声明和定义分开,即把print_inline()函数的定义放到另外一个文件print_inline.c中,结果就不一样了,在main.i文件中得内容变为了
# 3 "main.c" 2
# 1 "print_inline.h" 1
inline void print_inline();
# 4 "main.c" 2
int main(int argc, char *argv[])
print_inline();
system("PAUSE");
这个时候,print_inline()函数将无法在main函数中内联,我们可以查看生成得main.s汇编代码中包含了如下
&&& call&&& _print_inline
&&&&&& 其实原理很简单,就是当用#include 包含一个文件得时候,预处理得时候会直接展开这一个文件,如果文件中放有某个函数的定义,事实上就相当于把该函数定义放在了这个包含这个文件(上面得例子中得print_inline.h)的文件(main.c)中,这样就可以在main中将print_inline函数内联展开
&&&&&& 在很多时候,由于某些函数需要经常被调用,为了加快程序的执行速度,经常要用到inline,但是如果inline函数的定义和声明是分开的,而在另外一个文件中需要调用这些inline函数得时候,内联是无法在这些调用函数内展开的(上面得第二个例子),只能调用。这样内联函数在全局范围内就失去了作用。解决的办法就是把内联函数得定义放在头文件中,当其它文件要调用这些内联函数的时候,只要包含这个头文件就可以了
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。mdk arm4 在编译程序时各个C文件,H文件及启动文_电子信息工程吧_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:42,662贴子:
mdk arm4 在编译程序时各个C文件,H文件及启动文收藏
mdk arm4 在编译程序时各个C文件,H文件及启动文件是如何被调用的?
登录百度帐号推荐应用
为兴趣而生,贴吧更懂你。或

我要回帖

更多关于 微信支付密码怎么解除 的文章

 

随机推荐