• More Effective C++ 条款34 如何在一个程序中结合C++和C


    1. C++和C混合使用的前提之一就是编译器产生兼容的目标文件(.lib和.dll等).所谓"兼容",指的是编译器在"预编译器相依的特性上"一致,如int和double大小,参数压栈机制等,只有在这个基础上才能讨论结合使用C++和C模块的问题.

    2. 在1的基础上,要结合使用C++和C的模块,主要有以下几点需要注意:

        1). name mangling(名称重整)

        Name mangling是C++用于支持函数重载的机制,它对重载的函数名称进行一定改变,使得每个函数具有独一无二的名称,由于C不支持函数重载,因此也就不需要name mangling.

        如果C++要调用C函数库的某个函数,如果不抑制name mangling,经由name mangling后的函数名称可能与C函数库的原函数名称不匹配,因此就会导致链接失败.解决方法就是使用extern C阻止name mangling,像这样:

    extern "C" 
    void simulate(int iterations);

        这样C++编译器在编译C++文件时就会避免对simulate进行name mangling,转而采用和C相同的命名方式.extern "C"只对接下来的一个函数有效,如果要同时为多个函数使用extern "C",可以使用中括号:

    extern "C" { 
        void drawLine(int x1, int y1, int x2, int y2);
        void twiddleBits(unsigned char bits);
        void simulate(int iterations);
        ...
    }
    View Code

        有时代码既有可能被C++使用也有可能被C使用:当用于C++时,可能需要使用extern "C",而用于C时不需要,可以利用C++预定义的的__cplusplus宏使得文件可以"通用于数种语言",像这样:

    #ifdef __cplusplus
    extern "C" {
    #endif
    void drawLine(int x1, int y1, int x2, int y2);
    void twiddleBits(unsigned char bits);
    void simulate(int iterations);
    ...
    #ifdef __cplusplus
    }
    #endif
    View Code

        (注:如果要结合使用C,assembler,Fortran,LISP,Forth等的函数库,也需要抑制name mangling而使用extern "C".并没有像extern "Fortran"这样的用法,因为extern "C"并不说函数以C写成,而是指明要抑制name mangling. )  

        具体用法参照:http://www.cnblogs.com/luxiaoxun/p/3405374.html 

        2). Statics的初始化

        程序的入口实际上并不是main,而是编译器提供的特殊函数(如 mainCRTStartup(void)等,见C/C++:对象初始化相关),在mainCRTStartup主要任务之一就是全局对象(包括static class对象,全局对象,namespace作用域内的对象以及文件作用域内的对象)的初始化工作,由于C++支持动态初始化(如全局变量int b=a;)而C仅支持静态初始化(见C/C++:对象初始化相关),因此全局对象的动态初始化涉及到动态初始化就应该在C++中撰写main,而将C main重命名为realMain,然后让C++ main调用realMain,像这样:

    extern "C" // implement this
    int realMain(int argc, char *argv[]); // C程序库的函数,用于完成主函数功能
    int main(int argc, char *argv[]) // C++代码
    {
    return realMain(argc, argv);
    }
    View Code

        3). 动态内存分配

        C动态内存分配和释放使用malloc(及其变种)和free函数,只涉及内存的分配和释放;而C++使用new和delete关键字,并自动调用对象的构造函数.malloc(及其变种)/free搭配使用,new/delete搭配使用,不能混淆.

        (注:个人认为只要彻底了解new和delete的内部机制,混用问题也不大,见Effective C++ 条款16)

        4). 数据结构的兼容性

        C和C++对于struct和内置类型变量是兼容的,因为C/C++对于struct的内存布局相同,但如果C++为struct加上非虚成员函数,由于struct内存布局不改变,其对象仍兼容于C,但如果加上虚函数,由于vtbl和vptr的存在,struct内存布局便发生改变,也就不再兼容于C.

        也就是说,在C和C++之间对数据结构做双向交流是安全的——前提是结构的定义式在C和C++中都可编译;如果为C++ struct加上非虚函数,虽然不再兼容于C,但可能不影响兼容性;其他改变如虚函数和继承等则会产生影响.

  • 相关阅读:
    kettle部分传输场景应用(每个作业都实验过啦)
    Java设计模式之《适配器模式》及应用场景
    Mysql笔记
    Spring知识点
    Java基础系列-浅拷贝和深拷贝
    前端-javascript知识点
    前端-jquery知识点
    Java基础系列-substring的原理
    Java设计模式之《抽象工厂模式》及使用场景
    Java基础系列-Enum深入解析
  • 原文地址:https://www.cnblogs.com/reasno/p/4878888.html
Copyright © 2020-2023  润新知