#1 C++概览::基础知识

发布于 2025-01-16  504 次阅读



一、基本概念
(一)基础程序

int main()
{
    return 0;
}
//一个C++程序

一个空的mian函数是最小的C++程序,这个程序不接收任何参数,也不进行任何实际工作。其中需要注意的部分有:
(1)"{}":表示成组的意思,在这里的组指示出了mian函数的函数体;
(2)"//":表示注释的意思,注释仅作为提示,不会被编译器编译;
(3)"mian":main是一个特殊的函数名,表示主程序,是整个程序中最先执行、最后结束的函数;
(4)"int":int是函数的返回类型,表示函数运行结束之后的返回值,也就是return之后的数据的类型,若希望不返回任何值,可以设为void。在main函数中,返回0用于表示程序执行成功,非0值表示程序执行失败;
(5)"()":紧跟在函数名之后的()表示函数的参数列表,也就是在调用函数时,为函数提供的一些“原材料”。对于main函数而言,可以使用的参数有int类型的argc和char*[]类型的argv,分别表示命令行参数的个数和存储命令行参数的字符串;

#include <iostream>

/*
using namespace std;
using std::cout;
using std::endl;
*/
int main()
{
    std::cout<<"hello,world"<<std::endl;
    //cout<<"hello,world"<<endl;
}

上述程序的作用是在屏幕上输出了字符串“hello,world”。
(1)"#include \":表示使用头文件“iostream”,这个头文件中涉及一些标准输入输出的代码,通过#include之后,就可以使用这个头文件实现的功能;头文件可以分为C++的库文件和用户自己编写的头文件,使用<文件名>来使用库文件,使用"文件名"来使用自己编写的头文件;
(2)"using namespace std":表示使用命名空间std中的所有内容,例如cout、endl等等,如果想单独使用其中的一部分,可以像下面两行一样单独使用;
(3)"std::cout":表示使用std中的cout,其中::表示作用域限定符,如果不在前面“using”,那么每次使用std中的内容时,就需要添加作用域限定符;
(4)"<<":表示输出流,可以理解为数据从右向左流动;同样地,也存在">>"表示数据从左向右流动;
(5)"cout"与"endl":cout可以理解为当数据流动到此处会打印输出到屏幕上,endl可以理解为换行;
(二)类型、变量和算数运算
1、声明

int x;

上面的int是一个类型,类型是一些值以及对于这些值所能进行的操作的集合。例如,整数和整数运算,向量和向量运算等等。
x表示变量的名称,这个名称在遵循命名规范的前提下,可以随意更改,但我们一般会用名称表示实际含义和作用,尤其是在有大量变量的情况下,有助于我们辨别每一个变量的用途。
变量是一个被命名的对象,而对象是存储某种类型值的内存空间,值则是一些二进制位,根据类型的不同赋予不同的含义。
整个的int x是一个声明语句,作用是为程序引入新的变量并指定该变量的类型。
2、类型
C++中提供了一些基本类型,每种基本类型都与硬件特性直接相关,其尺寸固定不变,也决定了其中所能存储的值的范围。
一般来说,我们使用char类型的尺寸作为基础尺寸,其他类型的尺寸则是char类型的整数倍。具体的尺寸依赖于底层硬件,在不同机器上可能不同,我们可以使用sizeof运算符得到一个类型的尺寸。
3、运算
在C++中,通常存在两种运算——算术运算和比较运算。
算术运算包括加、减、乘、除、取余等等;
比较运算包括相等、大于、小于等等。
对于C++的基本类型,在进行运算的过程中,可能会在类型之间进行类型转换,以便多种类型之间的混合运算。
4、初始化
在C++中,提供了两种初始化的方式:
(1)使用"="进行初始化,例如int x = 5
(2)使用"{}"进行初始化,例如int x {5}
对于常量必须在声明时进行初始化,对于变量则不做要求,但一般来说,我们最好还是对变量赋予一个初始值。
5、推断类型
在定义一个变量时,如果变量的类型可以通过初始化器推断得到,那么我们就不需要显式指定其类型,而是可以使用auto,例如auto x=1,此时x的类型自动设置为了int。
(三)常量
C++中支持两种不变性概念:
const:可以理解为“承诺不改变这个值”,常用于函数的接口,可以避免变量在函数内被改变。
constexpr:可以理解为“在编译时求值”,作用是允许将数据置于只读内存中以提高性能。
(四)检验和循环
与C类似,C++中也提供了检验和循环语句,例如if-else if-else switch-case-default while- for-
(五)指针、数组和循环
1、指针
char *p可以声明一个指针,其中*表示“指向……”,这个指针p指向的类型为char,p中存储的数据是它指向的地址,什么都不指向的指针称为空指针,我们令它取值为nullptr
char x=*p中的前置一元运算符*表示“……的内容”,取出p指向空间的内容赋给x;
char *p=&x中的前置一元运算符&表示“……的地址”,取出x所在空间的地址赋给p;
2、数组
char c[5]可以声明一个数组,其中含有5个char类型的数据,[]表示“……的数组”,其中的数字是数组的下标,所有数组的下标是从0开始的,因此c包含的元素是c[0]c[4]
二、用户自定义类型
在C++中,允许用户自定义自己的数据类型,常见的自定义类型有结构、类和枚举。
(一)结构

struct Person{
private:
    char *name;//指向姓名的指针
public:
    int age;//表示年龄的整数
protected:
    int salary;//表示工资的整数
}

在定义完这样一个结构之后,我们可以像使用内置类型一样声明一个Person类型的变量,例如Person Ming
在C++中,我们可以使用public protected private来表示自定义类型中元素的访问权限:
public:允许外来访问、派生访问和自我访问;
protected:允许派生访问和自我访问;
private:仅允许自我访问;
对于struct而言,如果不显式声明访问权限,默认权限为public
(二)类

class Person{
private:
    char *name;//指向姓名的指针
public:
    int age;//表示年龄的整数
protected:
    int salary;//表示工资的整数
}

类与结构十分相似,只不过对于class而言,如果不显式声明访问权限,默认权限为private
在类中,可以声明和实现一些成员函数,也就是对这种类型数据运算的实现,例如打印函数等;也会存在一些必须实现的函数,例如构造函数、析构函数等,这些函数如果不实现,会由编译器自动生成无参版本。
在C++的结构中,同样支持在struct中声明和实现函数。
(三)枚举
enum class Color{red,blue,green}
enum class TrafficLight{red,yellow,green}
枚举类型通常用于描述规模较小的值的集合。
在不同枚举的作用域中可能存在同名的枚举值,我们可以使用作用域限定符的形式使它们互不干扰:
Color::red表示Color中的red。
TrafficLight::red表示TrafficLight中的red。
三、模块化
C++程序中包含许多独立开发的部分,构造C++程序的关键就在于清晰地定义这些组成部分之间的交互关系,最重要的一步是将组成部分的接口和实现分离开。
(一)分离编译
C++支持一种名为分离编译的概念,用户在使用函数的时候只能看见函数的类型和声明,其实现则存放在其他的源文件中,这有利于减少编译的时间。
一般我们将描述模块接口的声明放置在“头文件”中,用户使用include将模块包含进程序以使用。
同样地,实现函数的“源文件”也需要包含头文件。
(二)名字空间
C++提供一种名为名字空间的机制,可以表达某些声明是属于同一个整体的,同时表面它们的名字不会与其他命名空间的同名冲突,在使用时,可以通过命名空间+作用域限定符的形式使用,例如std::cout
(三)错误处理
1、异常
面对一些可能出现的异常,例如访问越界,一个好的办法是由实现者负责检测异常,随后通知使用者。常见的处理方法有通过if条件或者通过throw抛出异常catch处理异常。
2、不变式
对于一个类型来说,其数据成员的数值是有一定实际意义的,这就意味着根据其实际意义会对其值有一定的范围上的要求,例如我们不能说一个人的年龄是负数。
保证类中的值是“有意义”,这样的一条声明称为类的不变式。建立类的不变式是类的构造函数的任务,要保证数据成员在即便在退出时其不变式依然成立。
3、静态断言
静态断言是以编译器报告错误信息的形式来告知所发生的问题,当不满足某种条件时,输出预先编译好的错误信息来告知错误。


学习是一段漫长的旅途