作为一个Android程序员,如果只会java、kotlin应用开发,前几年还能混得开,这几年有点吃力了。
JNI开发越来越成为一个高级Android程序员的必备技能,所以我换工作以后第一件事就是把C++的学习纳入计划。
更重要的是,现在AI大模型太火了,有一些开源大模型是通过C++来做的,如果想要在客户端集成大模型,那么C++不说精通,至少要懂。
这个系列主要记录我学习C++的过程,算是一个笔记也是一个复盘的过程。
我学习C++主要是通过看书和视频,书是C++ Primer Plus,视频是B站上的黑马程序员视频。
今天第一篇主要是C++入门,涉及到C++ Primer Plus的第二章内容。
main函数
int main(int argc, char const *argv[])
{
return 0;
}
和java一样,C++的入口函数也是main函数,函数的定义和Java没什么区别。
头文件
#include<iostream> // 头文件
int main(int argc, char const *argv[])
{
//std是命名空间
std::cout << "hello C++" << std::endl;
return 0;
}
如上代码,和Java中不同的是,C++中没有导包的概念,取而代之的是头文件。
使用#include关键字来导入。
头文件的意思就是在当前代码中导入某个文件,比如上面的代码,就是在当前代码中导入了iostream这个文件中的所有编写的代码。
在开发工具中,可以直接点进iostream中查看。
和Java不同的是,Java中import导包,是把一个类导入到当前代码,C++中的头文件指的是一个文件,在这个文件中也许会包含多个类的对象。
命名空间
命名空间这个概念在Java中用的比较少,但是在C++中使用非常普遍,比如上面的这行代码:
std::cout << "hello C++" << std::endl;
std:就是头文件iostream中的一个命名空间; cout:是头文件iostream中定义的一个对象 <<:是一个一个插入运算符。 endl:代表换行
上面代码的意思是,通过std命名空间调用cout对象,使用<<运算符把后面的字符串出入到输出流中,显示出来。
命名空间调用对象有点类似Java中对象调用函数,或者是类调用静态函数,只不过使用的是::来完成调用。
C++中命名空间的概念比Java中类的概念更大,导入头文件以后,一般头文件中的对象都在命名空间中定义,所以调用的时候需要使用std::来调用
命名空间省略写法
#include<iostream> //头文件
int main(int argc, char const *argv[])
{
//命名空间单独提出来,下面调用对象的时候就可以省略std了
using namespace std;
//直接调用
cout << "hello C++" << endl;
return 0;
}
如上代码,如果使用using namespace std;单独提出来,下面使用cout对象就可以省略std了。但是尽量少用这种引入命名空间的方式,因为使用std::的方式进行调用,一眼就能看出这个对象或者函数是系统定义的,避免和个人定义的函数混淆。
C++标准库的组织方式
和Java一样,C++也提供了很多标准库供开发者调用,类似Android中提供的SDK。
C++中几乎所有的标准库都在std命名空间中,也就是说导入的所有标准库头文件,如果你要使用头文件中的对象或者函数,都需要使用std::来调用。
为什么这么设计?
一方面是为了统一命名空间,明确来源,一眼就能看出来某个对象或者函数来自标准款;一方面是防止和用户代码冲突。
具体那些对象和函数位于哪个头文件中,这就需要自己记忆,类似Java中一个类中有哪些函数,熟能生巧的过程。
函数
C++中函数定义和调用和Java中区别不大,唯一的区别是如上所述,C++中一般使用命名空间的方式进行调用系统定义的标准库函数,如下:
//sqrt是求平方根的函数
double b = std::sqrt(9.5);
其他的返回值、参数等都和Java类似,void代表没有返回值
函数的声明和定义分离
和Java中不同的是,C++的main函数如果要调用自己定义的函数,自定义函数不能再main函数的下方,如下这种方式会运行报错:
#include<iostream> //头文件
int main(int argc, char const *argv[])
{
using namespace std;
cout << "hello C++" << endl;
//调用函数,因为test函数再main函数下面定义,这里会报错,找不到test函数
test();
return 0;
}
void test(){
std::cout << "this is Test function" << std::endl;
}
因为C++的编译方式的单遍编译,编译器从上到下编译代码,只编译一遍,所以main函数中调用的所有自定义的函数都需要再main函数之前定义或者声明。
而Java是多遍编译,Java编译器会先扫描整个类,收集所有函数信息,然后再编译方法体,所以函数定义的顺序就无所谓。
出现这种差异的主要原因是,C++出现比较早,那个时期的计算机内存比较少,单遍编译比较节省内存,而Java出现以后,计算机内存已经比较大,所以为了简化程序员的工作,采用这种变异方面。
基于上面的要求,C++中会出现函数的声明和定义分离的情况,即,在main函数之前声明函数,在main函数后面定义函数,如下:
#include<iostream> //头文件
void test(int); //先声明
int main(int argc, char const *argv[])
{
using namespace std;
cout << "hello C++" << endl;
//调用函数
test(1);
return 0;
}
//再定义
void test(int a){
std::cout << "this is Test function" << std::endl;
}
结语
目前来看,C++和Java的主要区别是,命名空间和函数声明定义分离。
头文件引入以后,需要命名空间来调用对象和函数,因为C++的单遍编译,所以函数的声明和定义出现了分离的情况。
其他的函数的定义、变量的声明等,都和Java中一样。