起因

此前,一直做前端开发,对后端技术,抱着不求甚解的态度。今觉此态度,已演化成沉重的桎梏。故而预借源码,去揣摩学习。然而,大都项目的底层,以C/C++实现,想一点一滴重拾起,这尘封已久的记忆。


环境

系统:macOs Monterey
处理器:Intel Core i5
IDE:Xcode

闲聊:

在IDE选择上,网上搜了下,说Xcode是苹果系统集成IDE,适合开发苹果APP且功能强大。就想下载下来玩一下。记得上学那会儿,在Windows上,老师推荐用的是MinGW。工作之后,看大哥们使用Visual Studio进行开发。网上视频中,有人推荐使用Vscode,更有甚者使用Vim,Vi命令直接开撸。对于学习C++代码而言,重要的是对C++源代码的编译过程,先有一定的理解。目前主流编译器是gcc、clang,可以通过man gcc ,查看编译器提供的编译指令,了解这些指令背后的意义,更好的去完成C++代码的编译和优化。


项目介绍

  • cplus_primer_01
  • main.cpp
  • MyClass.cpp
  • MyClass.h

想要通过main函数,调用自定义类MyClass的Compute方法。

main.cpp

#include <iostream>
#include "MyClass.h"
int main(int argc, const char * argv[]) {
    // insert code here...
    std::cout << "Hello, World!"<<std::endl;
    MyClass my_class = MyClass();
    std::cout << my_class.Compute(3, 5) << std::endl;
    return 0;
}

MyClass.h

#ifndef MyClass_h
#define MyClass_h
class MyClass{
 public:
    MyClass();
    int Compute(int a, int b);
};
#endif

MyClass.cpp

#include "MyClass.h"
int MyClass::Compute(int a, int b){
    return a + b;
};

问题描述

哦豁,编译的时候,弹出编译错误如下:

c编译出错 ios ios端c++编译器_c++


原因分析:

看字面意思是:在链接的时候,没有找到main.cpp中,MyClass的构造函数。(之前项目开发一直用C#,项目build过程,IDE一键完成。主要精力放在编译报错和业务调试环节。这次遇到这个提示挺有意思的
网上查了一下,c++程序的编译经过以下几个环节:


Created with Raphaël 2.3.0 main.cpp 预编译 main.cpp 生成预编译后的代码 main.ii 编译 main.ii 生成汇编代码 main.s 汇编转机器码 main.s 生成目标环境二进制代码main.o 库文件、其他目标文件 连接 main.o、libs 生成可执行文件 a.exe


1.预编译

  • 将.cpp 文件转化成 .ii文件
  • 使用的clang++命令是:clang++ –E

2.编译

  • 将.ii 文件转换成.s文件
  • 使用的clang++命令是:clang++ –S

3.汇编

  • 将.s 文件转化成 .o文件
  • 使用的clang++命令是:clang++ –c

4.链接

  • 将.o 文件转化成可执行程序
  • 使用的clang++ 命令是: clang++

man clang 查到有指令参数 -save-temps 可以将编译中间步骤产生的文件存储下来。

clang++ -save-temps main.cpp MyClass.cpp
ls -alF

c编译出错 ios ios端c++编译器_xcode_02


查看预编译后生成的文件 main.ii

c编译出错 ios ios端c++编译器_macos_03


看到已经将MyClass.h的类声明给带入进来了!

看到预编译,已经将头文件类声明拷贝到此处。

说明不是头文件找不到,而是类定义的时候出了问题。

再看编译报错的原因,Undefined Symbols ,MyClass::MyClass() 未定义的标识。未定义?难道是对构造函数没有显示定义?因为印象里,构造函数是创建类的时候,编译器会帮我定义的。所以我只在头文件中,声明了一下,而在cpp文件里,没有对它实现。


解决方案:

在头文件中,去掉了构造函数的声明,编译通过。

MyClass.h

#ifndef MyClass_h
#define MyClass_h
class MyClass{
 public:
    int Compute(int a, int b);
};
#endif

总结

起初,由于对IDE和C++双重不熟,确定不了是编译配置的问题,还是代码链接的问题,走了不少弯路。现在看下来,其实编译器早就明确的告诉我错误的原因了。

写此文做为一个开始。