zoukankan      html  css  js  c++  java
  • 链接工作过程

    链接的作用是找到每个符号和函数的位置,并且将它们连接在一起。每个obj文件之间是没有联系的,这些文件实际上没法相互沟通,所以需要将他们连接到一个程序中来。即使程序只有一个cpp文件,程序入口主函数和一些其他的东西仍需要被链接。

    Math.cpp

    #include<iostream>
    
    void Log(const char* message)
    {
        std::cout<<message<<std::endl;
    }
    
    int Multiply(int a,int b)
    {
        Log("Multiply");
        return a*b;
    }

    如果按ctrl+F7进行编译,会编译成功,但是按F5进行build会报错:"entry point must be defined",因为缺少入口点main函数。

    程序的声称是经过编译和链接两个步骤的,如果去掉函数的大括号,编译时就会报错,error后面会有C表示错误来自编译,来自链接的错误在控制台中用LINK表示。

    unresolved external symbo(未解决的外部符号),当链接器找不到他需要的东西时就会这样报错。

    Log.cpp

    #include<iostream>
    
    void Logr(const char* message)
    {
        std::cout<<message<<std::endl;
    }

    Math.cpp

    #include<iostream>
    
    void Log(const char* message);
    
    int Multiply(int a,int b)
    {
        Log("Multiply");
        return a*b;
    }
    
    int  main()
    {
        std::cout<<Multiply(5,8)<<std::endl;
        std::cin.get();
    }

    在链接时就会出现这种错误,如果在Multiply函数中注释掉Log函数,那么不会报错,但是将main中的cout<<Multiply注释掉,还是会报错

    如果在Multiply中删掉,那么Log函数就成了彻底没有被使用的死代码了,但是第二种情况Log还是有可能被使用的,在其他的cpp文件中,所以Linker需要链接他。

    如果说明只在Math.cpp文件中使用Multiply函数,那么可以消除Link的必要。改变方法就是将Multiply函数设成静态

    #include<iostream>
    
    void Log(const char* message);
    
    static int Multiply(int a,int b)
    {
        Log("Multiply");
        return a*b;
    }
    
    int  main()
    {
        //std::cout<<Multiply(5,8)<<std::endl;
        std::cin.get();
    }

    这样连接时就不会报错

    当两个函数具有一样的名字,类型和返回值时,链接会出错,因为Linker不知道该链接哪个,将Math.cpp修改

    #include<iostream>
    
    void Log(const char* message);
    
    void Log(const char* message)
    {
        std::cout<<message<<std::endl;
    }
    
    static int Multiply(int a,int b)
    {
        Log("Multiply");
        return a*b;
    }
    
    int  main()
    {
        //std::cout<<Multiply(5,8)<<std::endl;
        std::cin.get();
    }

    此时链接就会出错,因为Log函数已经在Log.cpp中被定义了,这样会找到一个或多个被定义的符号。

    常见错误

    log.h

    #pragma once
    
    void Log(const char* message)
    {
        std::cout<<message<<std::endl;
    }

    Log.cpp

    #include<iostream>
    #include"Log.h"
    
    void InitLog()
    {
        Log("Initialized Log");
    }

    Math.cpp

    #include<iostream>
    #include"Log.h"
    
    static int Multiply(int a,int b)
    {
        Log("Multiply");
        return a*b;
    }
    
    int main()
    {
        std::cout<<Multiply(5,8)<<std::endll;
        std::cin.get();
    }

    链接时出现错误,说Log在Log.obj中已经定义,在代码中只有log.h定义了Log函数,为什么链接时会报错定义多次呢?

    因为在include时,头文件的内容会放到include语句的位置上,因此上述代码中,Log函数分别在Log.cpp和Math.cpp中定义了两次

    那么怎么解决呢?将log.h中的Log设置成静态

    #pragma once
    
    static void Log(const char* message)
    {
        std::cout<<message<<std::endl;
    }

    这意味着函数链接时链接只应该发生在文件内部,所以Math.cpp和Log.cpp都会有自己版本的Log函数,它对其他obj文件都是不可见的

    另一个改正方法是使用内联函数inline

    #pragma once
    
    inline void Log(const char* message)
    {
        std::cout<<message<<std::endl;
    }

    inline的意思是把函数的身体直接拿过来取代调用,在这种情况下,Log.cpp中代码相当于这样

    #include<iostream>
    #include"Log.h"
    
    void InitLog()
    {
        std::cout<<"Initialized Log"<<std::endl;
    }

    InitLog函数内部调用的Log函数直接变成了Log函数的结构。

    也可以改变Log函数的位置

    Log.h

    #pragma once
    
    inline void Log(const char* message);

    Log.cpp

    #include<iostream>
    #include"Log.h"
    
    void InitLog()
    {
        Log("Initialized Log");
    }
    
    void Log(const char* message)
    {
        std::cout<<message<<std::endl;
    }

    这样编译链接也不会报错

  • 相关阅读:
    halcon三种模板匹配方法
    线阵相机与面阵相机的区别
    完整性检测
    halcon读取一张照片,并转化为灰度图像
    halcon车牌的识别
    HALCON学习之条形码实时扫描
    开关引脚测量
    ip sensor芯片级解决方案
    ip camera芯片级解决方案
    Parallel For Bug in static constructor
  • 原文地址:https://www.cnblogs.com/wangtianning1223/p/12606240.html
Copyright © 2011-2022 走看看