C++中的内部连接与外部连接(二)

SpitFire原创,CSDN首发,转贴请说明出处,谢谢。

欢迎大家来这里讨论问题 http://www.allaboutprogram.com/bb/index.php

      c)类定义总有内部连接,而非inline类成员函数定义总有外部连接,不论这个成员函数是静态、虚拟还是一般成员函数,类静态数据成员定义总有外部连接。

             1.类的定义有内部连接。如果不是,想象一下你在4cpp文件中include定义了类Base的头文件,在4个编译单元中的类Base都有外部连接,在连接的时候就会出错。

             看下面的例子:

           //main.cpp

           class B                                   //类定义,内部连接

           {

                 static int s_i;                     //静态类成员声明,内部连接             

           public:

                  void foo() { ++s_i;} //inline函数,内部连接

           };

           struct D

           {

                  void foo();                     //类成员函数声明,内部连接

           };

           int B::s_i = 0;                            //类静态数据成员定义,外部连接

           void D::foo()                       //类成员函数定义,外部连接

           {

                  cout << "D::foo in main.cpp" <<endl;

           }

           int main()                                 //main函数,全局自由函数,外部连接

           {

             B b;

             D d;

             return 0;

           }

          

           //a.cpp

           class B

           {

                  int k;

           };

          

           struct D

           {

                  int d;

           };

在这个例子中,main.cppa.cpp中都有class Bclass D的定义,但在编译这两个cpp文件时并不发生link错误。

               2.类的非inline成员函数(一般,静态,虚拟都是)总有外部连接,这样当你include了某个类的头文件,使用这个类的函数时,就能连接到正确的类成员函数上,继续以上面为例子,如果把a.cpp中的struct D改为

                struct D                       //类定义

                {

                  int d;

                  void foo();                    //类成员函数声明

                };

                void D::foo()                 //类成员函数定义,外部连接

                {

                  cout << " D::foo in a.cpp" <<endl;

                }

               

       这时main.cppa.cpp中的D::foo都有外部连接,在连接就会出现multiply defined symbols错。

              3.类的静态数据成员有外部连接,如上例的B::s_i,这样当你在main.cpp中定义了类静态数据成员,其它编译单元若使用了B::s_i,就会连接到main.cpp对应编译单元的s_i

                

       d)inline函数总有内部连接,不论这个函数是什么函数

              // main.cpp

             

              inline int foo() { return 1;}          //inline全局函数,内部连接

              class Bar                                     //类定义,内部连接

              {

              public:

                     static int f() { return 2;}       //inline 类静态函数,内部连接

                     int g(int i) { return i;}       //inline 类成员函数,内部连接

              };

              class Base

              {

              public:

                     inline int k()                    //类成员函数声明,内部连接

              }

              inline int Base::k(){return 5;}   //inline 类成员函数,内部连接

             

              int main(void)

              {

                     return 0;

              }

      

       如果你的Base类是定义在Base.h中,而Baseinline 函数是在Base.cpp中定义的,那么在main.cppinclude "Base.h"编译不会出现问题,但在连接时会找不到函数k,所以类的inline函数最好放到头文件中,让每一个包含头文件的cpp都能找到inline函数。

      

现在对c++中的连接有了一个认识,能清楚的知道是什么原因产生连接时错误。当你在连接时产生连接不到的错误,这说明所有的编译单元都没有这个实体的外部连接;当你在连接时发现有多个连接实体,这说明有多个编译单元提供了同名的有外部连接的实体。同时,在进行程序设计时,也要注意不要使只有本编译单元用到的函数、类、变量等有外部连接,减少与其它编译单元的连接冲突。

 

不过在这里没有说明template函数及template class的连接性,并且对一些特别的情况也没有作出说明(比如inline函数不能被inline),欲知后事如何,且听下回分解 :)

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
组织和策略问题 1 第0条 不要拘泥于小节(又名:了解哪些东西不应该标准化) 2 第1条 在高警告级别干净利落地进行编译 4 第2条 使用自动构建系统 7 第3条 使用版本控制系统 8 第4条 做代码审查 9设计风格 11 第5条 一个实体应该只有一个紧凑的职责 12 第6条 正确、简单和清晰第一 13 第7条 编程应知道何时和如何考虑可伸缩性 14 第8条 不要进行不成熟的优化 16 第9条 不要进行不成熟的劣化 18 第10条 尽量减少全局和共享数据 19 第11条 隐藏信息 20 第12条 懂得何时和如何进行并发性编程 21 第13条 确保资源为对象所拥有。使用显式的RAII和智能指针 24 编程风格 27 第14条 宁要编译时和连接时错误,也不要运行时错误 28 第15条 积极使用const 30 第16条 避免使用宏 32 第17条 避免使用“魔数” 34 第18条 尽可能局部地声明变量 35 第19条 总是初始化变量 36 第20条 避免函数过长,避免嵌套过深 38 第21条 避免跨编译单元的初始化依赖 39 第22条 尽量减少定义性依赖。避免循环依赖 40 第23条 头文件应该自给自足 42 第24条 总是编写内部#include保护符,决不要编写外部#include保护符 43 函数与操作符 45 第25条 正确地选择通过值、(智能)指针或者引用传递参数 46 第26条 保持重载操作符的自然语义 47 第27条 优先使用算术操作符和赋值操作符的标准形式 48 第28条 优先使用++和--的标准形式。优先调用前缀形式 50 第29条 考虑重载以避免隐含类型转换 51 第30条 避免重载&&、||或 ,(逗号) 52 第31条 不要编写依赖于函数参数求值顺序的代码 54 类的设计与继承 55 第32条 弄清所要编写的是哪种类 56 第33条 用小类代替巨类 57 第34条 用组合代替继承 58 第35条 避免从并非要设计成基类的类继承 60 第36条 优先提供抽象接口 62 第37条 公用继承即可替换性。继承,不是为了重用,而是为了被重用 64 第38条 实施安全的覆盖 66 第39条 考虑将虚拟函数声明为非公用的,将公用函数声明为非虚拟的 68

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值