include cpp?还可以这样?

前两天突然看见部门有个项目的代码里通篇全是#include "xxx.cpp",我表示从来没见过这种写法,引发了我的一些思考:

图片

问题一:这啥玩意?

C++是一门高深莫测的语言,什么写法都有,而且#include本质上就是复制粘贴代码,我也不敢说别人写的不对,可能开发者是C++大佬,写了一些我们普通人无法理解的代码也是正常的。

 

问题二:整个项目都是这种引用方式,不会导致某一函数重复定义吗?

为此我查了一些资料,并做了一些测试:

 

代码段1:

// file1.cc
#include <iostream>

using std::cout;

 void ddd() { cout << "ddd \n"; }

 

代码段2:

// file2.cc
#include "file1.cc"

int main() {
    ddd();
    return 0;
}

 

代码段3:

// filec.cc
#include "file1.cc"

void f() {
    ddd();
}

 

然后三个源文件一起编译链接:

图片

 

发现报错了,的确出现了multiple definition的错误,确实一个函数不能有多个定义。我又改了下代码:

// file1.cc
#include <iostream>

using std::cout;

inline void ddd() { cout << "ddd \n"; }

 

将ddd函数改成了内联函数,然后三个源文件一起编译链接:

图片

 

编译成功且正常输出。

 

我将普通函数改成成员函数又测试了一次:

 

代码段1:

file1.cc
#include <iostream>

using std::cout;

struct A {
    int a_;
    void func();
};

void A::func() { cout << "file1.cc a " << a_ << "\n"; }

 

代码段2:

// file2.cc
#include "file1.cc"

int main() {
    A a;
    a.func();
    return 0;
}

 

代码段3:

// filec.cc
#include "file1.cc"

void f() {
    A a;
    a.func();
}

 

然后一起编译链接:

图片

 

发现成员函数这样定义也会报错,也会有multiple definition的错误,我又改了一下代码:

// file1.cc
#include <iostream>

using std::cout;

struct A {
    int a_;
    void func() { cout << "file1.cc a " << a_ << "\n"; }
};

 

将函数的定义搬运到了类中,编译链接:

图片

程序正常运行,熟悉C++的朋友可能都知道原因,类中定义的函数就相当于是内联函数,所以编译链接不会有问题。

 

所以得出结论:

  • 内联函数的定义可以被多个源文件引入(内联函数到最后其实不是个函数)

  • 类的定义可以被多个源文件引入(这是必须的,要不然编译器怎么知道类的对象布局)

 

问题三:貌似平时使用的模板就多数都定义在头文件中,这个不会导致某一函数重复定义吗?

 

直接看三段代码吧:

 

代码段1:

// temp.h
#include <iostream>

template <typename T>
struct B {
    T a;
    void ff() { std::cout << "temph \n"; }
};

代码段2:

// filec.cc
#include "temp.h"

void f() {
    B<int> a;
    a.ff();
}

代码段3:

// file2.cc
#include "temp.h"

int main() {
    B<int> a;
    a.ff();
    return 0;
}

所有源文件编译链接:

图片

发现编译成功且正常运行,那如果函数的定义不在类内会怎么样呢?

// temp.h
#include <iostream>

template <typename T>
struct B {
    T a;
    void ff();
};

template <typename T>
void B<T>::ff() {
    std::cout << "temph \n";
}

程序编译链接后:

图片

编译链接成功且输出正常结果。

 

所以得出结论:编译器对模板做了特殊处理,不论模板类中函数是否内联,都可以正常链接。

 

这个结论其实不是我得出的(所以可信),而是gnu文档(参考资料的最后一个链接)写的,上述代码只是为了印证结论。

 

大体意思如下:编译器对模板做了特殊处理,如果函数不是内联函数,那可以有两种处理方式:

  1. 链接时随机选择一个定义,其它的丢弃掉

  2. 编译器会把函数的定义单独提出来,提到单独一个文件中,对此文件单独编译,就不会出现重复定义的问题。

 

搞定,大家对此还有什么问题,欢迎留言!

 

参考资料

https://zybuluo.com/uuprince/note/81709

https://stackoverflow.com/questions/15866258/template-class-multiple-definition

https://gcc.gnu.org/onlinedocs/gcc/Template-Instantiation.html

  • 9
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
========= Cppcheck ========= About The original name of this program is "C++check" but it was later changed to "cppcheck". Manual A manual is available online: http://cppcheck.sourceforge.net/manual.pdf Compiling Any C++11 compiler should work. For compilers with partial C++11 support it may work. If your compiler has the C++11 features that are available in Visual Studio 2010 then it will work. If nullptr is not supported by your compiler then this can be emulated using the header lib/cxx11emu.h. To build the GUI, you need Qt. When building the command line tool, PCRE is optional. It is used if you build with rules. There are multiple compilation choices: * qmake - cross platform build tool * cmake - cross platform build tool * Windows: Visual Studio * Windows: Qt Creator + mingw * gnu make * g++ 4.6 (or later) * clang++ qmake ===== You can use the gui/gui.pro file to build the GUI. cd gui qmake make Visual Studio ============= Use the cppcheck.sln file. The file is configured for Visual Studio 2013, but the platform toolset can be changed easily to older or newer versions. The solution contains platform targets for both x86 and x64. To compile with rules, select "Release-PCRE" or "Debug-PCRE" configuration. pcre.lib (pcre64.lib for x64 builds) and pcre.h are expected to be in /extlibs then. Qt Creator + mingw ================== The PCRE dll is needed to build the CLI. It can be downloaded here: http://software-download.name/pcre-library-windows/ gnu make ======== Simple build (no dependencies): make The recommended release build is: make SRCDIR=build CFGDIR=cfg HAVE_RULES=yes Flags: SRCDIR=build : Python is used to optimise cppcheck CFGDIR=cfg : Specify folder where .cfg files are found HAVE_RULES=yes : Enable rules (pcre is required if this is used) g++ (for experts) ================= If you just want to build Cppcheck without dependencies then you can use this command: g++ -o cppcheck -std=c++0x -include lib/cxx11emu.h -Iexternals/tinyxml -Ilib cli/*.cpp lib/*.cpp externals/tinyxml/*.cpp If you want to use --rule and --rule-file then dependencies are needed: g++ -o cppcheck -std=c++0x -include lib/cxx11emu.h -lpcre -DHAVE_RULES -Ilib -Iexternals/tinyxml cli/*.cpp lib/*.cpp externals/tinyxml/*.cpp mingw ===== The "LDFLAGS=-lshlwapi" is needed when building with mingw mingw32-make LDFLAGS=-lshlwapi other compilers/ide =================== 1. Create a empty project file / makefile. 2. Add all cpp files in the cppcheck cli and lib folders to the project file / makefile. 3. Compile. Cross compiling Win32 (CLI) version of Cppcheck in Linux sudo apt-get install mingw32 make CXX=i586-mingw32msvc-g++ LDFLAGS="-lshlwapi" mv cppcheck cppcheck.exe Webpage http://cppcheck.sourceforge.net/

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序喵大人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值