zoukankan      html  css  js  c++  java
  • c++ 前向申明(ForwardDeclaration)待整理

    1、c++的#include的预编译

         例如:#include<iostream>
          该预编译指令导致预处理器将iostream文件的内容添加到程序中。 #指令:预处理指令以#号开头,并且#号必须是该行除了任何空白字符外的第一个字符。
    #后是指令关键字,在关键字和#号之间允许存在任意个数的空白字符。整行语句构成了一条预处理指令,该指令将在编译器进行编译之前对源代码做某些转换。#include预处理指令的作用是在指令处展开被包含的文件。展开被包含的文件之后,代码就可以正常地调用该文件中所声明的变量和函数。#include指令有两种使用方法:第一种:#include <xxx.h>  第二种:#include "xxx.h"。
      第一种方法将待包含的头文件使用尖括号括起来,预处理程序会在系统默认目录或者括号内的路径查找,通常用于包含系统中自带的公共头文件。
      第二种方法将待包含的头文件使用双引号引起来,预处理程序会在程序源文件所在目录查找,如果未找到则去系统默认目录查找,通常用于包含程序作者编写的私有头文件

    2、c++中的单独编译

      c++允许甚至程序员将组件函数放在独立的文件中,可以单独编译这些文件,然后将它们链接成可执行的程序。
    • 首先,我们可以将所有东西都放在一个.cpp文件内,然后编译器就将这个.cpp编译成.obj。就是编译单元了,一个程序,可以由一个编译单元组成,也可以有多个编译单元组成.。如果你不想让你的源代码变得很难阅读的话,就请使用多个编译单元吧(一个函数不能放到两个编译单元里面,但两个以上就可以分别放在一个单元,也就是cpp里面)。那么就是一个.cpp对应一个.obj,然后将所有的obj链接起来(通过一个叫链接器的程序),组成一个.exe,也就是程序了。如果一个.cpp要用到另一个.cpp定义的函数怎么办? 只需在这个.cpp种写上他的函数声明就可以了。其余工作由链接器帮你完成,你可以随便调用该函数。

    • c++程序预编译和链接阶段是分开的,更加详细需要了解编译原理,声明仅仅是将一个符号引入到一个作用域。而定义提供了一个实体在程序中的唯一描述。在一个给定的定义域中重复声明一个符号是可以的 , 但是却不能重复定义 , 否则将会引起编译错误。在编译时,编译器只检测程序语法和函数、变量是否被声明。如果函数未被声明,编译器会给出一个警告,但可以生成目标文件。而在链接程序时,链接器会在所有的目标文件中找寻函数的实现。如果找不到,那到就会报链接错误码( Linker Error)。在 VC 下,这种错误一般是: Link 2001 错误,意思说是说,链接器未能找到函数的实现。链接把不同编译单元产生的符号联系起来。有两种链接方式:内部链接和外部链接。

    3、c++中的前向声明以及两个类相互包含引用问题

    •  前向声明:可以声明一个类而不定义它。这个声明被称为前向声明(forward declaration)。例如:class name。在声明之后,定义之前,类name是一个不完全类型(incompete type),即已知name是一个类型,但不知道包含哪些成员。不完全类型只能以有限方式使用,不能定义该类型的对象,不完全类型只能用于定义指向该类型的指针及引用或者用于声明(而不是定义)使用该类型作为形参类型或返回类型的函数
      类的前向声明只适用于指针和引用的定义,如果是普通类类型就得使用include了。 
    • 两个类之前的相互引用包含问题。

      在构造自己的类时,有可能会碰到两个类之间的相互引用问题,例如:定义了类A类B,A中使用了B定义的类型,B中也使用了A定义的类型。

    class A
    {
          int i;
          B b;
    }
    class B
    {
          int i;
          A* a;
    }

      请注意上面的定义内容,一般情况下是不能出现类A,类B相互引用都定义对象,即如下的样子:

    class A
    {
        int i;
        B b;
    }
    class B
    {
         int i;
         A a;
    }

      在这种情况下,想想能够有a.b.a.b.a.b.a.b.a.b…………,很有点子子孙孙无穷尽之状,那么我的机器也无法承受。最主要的还是这种关系很难存在,也很难管理。这种定义方式类同程式中的死循环。所以,一般来说,两者的定义,至少有一方是使用指针,或两者都使用指针,但是决不能两者都定义实体对象。

    //class A.h
    #include "B.h"
    class A
    {
         int i;
         B b;
    }
    //class B.h
    class A;
    class B
    {
        int i;
        A *a;
    }
    //B.cpp
    //在B.cpp中的文档包含处要有下面语句,否则不能调用成员a的任何内容
    #include "A.h"
    B::B()
    {
        ……
    }
      当两个类互相包含和互相在本类中定义另外一个类的对象指针引用时,必须保证当一个类先声明或者定义时候才可以在另外一个类中使用,如在类A的前面声明Class B or 在B类前声明Class A。这种方法是只适用于用来定义类指针或者类应用,而不能来定义类对象变量或者函数的变量名。这是因为上面仅仅声明了类 ,说明这个类是一个标识,还没有实现所以不能定义对象变量。
      但是对于如果想要在一个类中定义对象来说比如在A.h文件中定义B类对象这样的话,就需要在A.h中包含B类头文件 #include “B.H” 。
    转自:https://blog.csdn.net/weixin_43081805/article/details/89916717
  • 相关阅读:
    Tomcat 容器的安全认证和鉴权
    Tomcat 中的 Session 和 Cookie
    Tomcat 类加载器的实现
    Tomcat 对静态资源的处理
    Tomcat 路由请求的实现 Mapper
    Tomcat 配置文件解析工具 Digester
    Tomcat 容器的设计和实现
    ArrayList 和 LinkedList 源码分析
    Mybatis自定义分布式二级缓存实现与遇到的一些问题解决方案!
    Dubbo序列化多个CopyOnWriteArrayList对象变成同一对象的一个大坑!!
  • 原文地址:https://www.cnblogs.com/z1141000271/p/14952049.html
Copyright © 2011-2022 走看看