C++ 进一步扩充和完善了 C 语言,像Java一样它也是一种面向对象的程序设计语言。
上一篇:C语言基础
1. 程序结构
让我们逐帧分析
#include <iostream>
using namespace std;
// main() 是程序开始执行的地方
int main()
{
cout << "Hello World"; // 输出 Hello World
// cout << "Hello, world!" << endl;
return 0;
}
#include <iostream>
:包含了输入输出流库 iostream
using namespace std
:告诉编译器使用标准命名空间( std
)
cout << "Hello World";
:
cout
: 是 C++ 中的标准输出流,用于向控制台输出信息。<<
: 是流插入运算符,用于将右侧的内容输出到左侧的流中。"Hello World"
: 是要输出的字符串。它将在控制台上显示。
return 0;
:终止 main( )函数,并向调用进程返回值 0
cout << "Hello, world!" << endl
输出 Hello, world! 的另一种写法,
<< endl
:endl
是一个特殊的操作符,它会在输出后插入一个换行符并刷新输出缓冲区。
2. 数据类型
类型 | 关键字 |
---|---|
布尔型 | bool |
字符型 | char |
整型 | int |
浮点型 | float |
双浮点型 | double |
无类型 | void |
宽字符型 | wchar_t |
详细介绍:
类型 | 描述 | 大小 | 值范围 |
---|---|---|---|
整数类型 | |||
int |
标准整数类型 | 通常 4 字节 | -2,147,483,648 到 2,147,483,647 |
short |
短整型 | 通常 2 字节 | -32,768 到 32,767 |
long |
长整型 | 4 或 8 字节 | 32 位系统与 int 相同,64 位系统可更大 |
long long |
更长整型 | 至少 8 字节 | -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807 |
浮点类型 | |||
float |
单精度浮点型 | 通常 4 字节 | ±3.4 × 10^−38 到 ±3.4 × 10^38 |
double |
双精度浮点型 | 通常 8 字节 | ±1.7 × 10^−308 到 ±1.7 × 10^308 |
long double |
长双精度浮点型 | 8 字节或更多 | 提供更大范围和更高精度 |
字符类型 | |||
char |
字符型 | 通常 1 字节 | -128 到 127 或 0 到 255 |
wchar\_t |
宽字符型 | 通常 2 或 4 字节 | 用于存储 Unicode 字符 |
布尔类型 | |||
bool |
布尔型 | 通常 1 字节 | 只有两个值:true 和 false |
更多类型:
数据类型 | 定义 | 示例代码 |
---|---|---|
枚举类型 (enum) | 用于定义一组命名的整型常量,提高代码可读性。 | enum Color { RED, GREEN, BLUE }; |
结构类型 (struct) | 用户定义的数据类型,组合不同类型的数据。 | struct Person { string name; int age; }; |
类类型 (class) | C++ 的核心特性,支持封装、继承和多态。 | class Car { public: string brand; int year; }; |
联合类型 (union) | 允许在同一内存位置存储不同类型的数据,只有一个成员占用存储空间。 | union Data { int intValue; float floatValue; char charValue; }; |
其他数据类型 | void: 表示没有类型,常用于函数返回类型。 | void function() { ... } |
指针类型: 用于存储变量的地址,以 * 前缀表示。 | int\* ptr; |
|
引用类型: 创建变量的别名,以 & 表示。 | int& ref = originalVar; |
|
类型修饰符 | 改变基本数据类型的属性。 | |
signed: 带符号类型(默认)。 | signed int a; |
|
unsigned: 无符号类型,扩展可表示的正整数范围。 | unsigned int b; |
|
short / long: 改变整型的大小。结合使用,例如 unsigned long。 | unsigned long c; |
注意: 不同系统会有所差异,一字节为 8 位。
注意: 默认情况下,int、short、long都是带符号的,即 signed。
注意: long int 8 个字节,int 都是 4 个字节,早期的 C 编译器定义了 long int 占用 4 个字节,int 占用 2 个字节,新版的 C/C++ 标准兼容了早期的这一设定。
在此不做进一步详细介绍,相比于菜鸟教程,那上面还有好多类型,而且C++还有很多标准,头大,还好C++不是我的主语言,这篇文章主打一个了解,够用!
2.2 typedef 声明(这个很常用)
使用 typedef 为一个已有的类型取一个新的名字
基本语法
typedef existing_type new_type_name;
示例:
typedef int Integer;
Integer a = 5; // 这里Integer是int的别名
typedef int* IntPtr;
IntPtr p1, p2; // p1和p2都是int指针
typedef int Array[10];
Array arr; // arr是一个包含10个整数的数组
struct Person {
std::string name;
int age;
};
typedef Person PersonType;
PersonType p; // p是Person结构体的一个实例
typedef void (*FuncPtr)(int, double);
void myFunction(int, double) { /* 函数实现 */ }
FuncPtr ptr = myFunction; // ptr是指向myFunction的函数指针
2.3 类型转换
C++提供了四种主要的类型转换:静态转换( static_cast
)、动态转换( dynamic_cast
)、常量转换( const_cast
)和重新解释转换( reinterpret_cast
)
2.3.1 静态转换 ( static_cast)
用于大多数基本类型之间的转换,如整型到浮点型;也可以用于类之间的转换(基类与派生类)。
int i = 10;
float f = static_cast<float>(i); // 静态将int类型转换为float类型
2.3.2 动态转换 ( dynamic_cast)
主要用于处理多态,安全地将基类指针或引用转换为派生类指针或引用。
class Base {};
class Derived : public Base {};
Base* ptr_base = new Derived;
Derived* ptr_derived = dynamic_cast<Derived*>(ptr_base); // 将基类指针转换为派生类指针
2.3.3 常量转换 ( const_cast)
用于去掉对象的常量性,允许修改一个常量对象。
const int a = 10;
int* b = const_cast<int*>(&a); // 去掉常量性
*b = 20; // 修改常量对象的值,可能导致未定义行为
2.3.4 重新解释转换 ( reinterpret_cast)
用于在不考虑数据类型的情况下转换指针或引用的类型。
int* p = reinterpret_cast<int*>(0x12345678); // 将地址转为 int 指针
char* c = reinterpret_cast<char*>(p); // 将 int 指针转为 char 指针
3. 变量类型
在C++中,变量是用来存储数据的命名内存位置。
3.1 变量定义
变量定义不仅声明了变量的名字和类型,而且为其分配内存并可选地初始化变量。
3.2 变量声明
变量声明是告诉编译器某个变量的名字和类型,但并不分配内存或初始化变量。声明的目的是让编译器知道该变量将要使用,以便在后续代码中进行类型检查。
extern int x; // 声明变量 x,类型为 int
变量声明及定义示例
#include <iostream>
using namespace std;
// 变量声明
extern int a, b;
extern int c;
extern float f;
int main ()
{
// 变量定义
int a, b;
int c;
float f;
// 实际初始化
a = 10;
b = 20;
c = a + b;
cout << c << endl ;
f = 70.0/3.0;
cout << f << endl ;
return 0;
}
3.3 左值与右值
左值(Lvalue)
左值(Left Value)是指可以出现在赋值运算符左侧的表达式,通常是指可以持久化存在的对象,具有可寻址性。换句话说,左值是一个具有持久存储的对象,它的地址是可以取出的。
int a = 5; // a 是一个左值
a = 10; // a 可以在赋值运算符左侧
右值(Rvalue)
右值(Right Value)是指不能出现在赋值运算符左侧的表达式,通常是临时对象或常量。右值一般是不能持久化存在的对象,它的值不能被直接修改。
int b = 5; // 5 是一个右值
b = a + 3; // a + 3 是一个右值
同大多数语言一样,没什么好说的,这里只是了解下。
4. 变量作用域
在 C++ 中,变量的作用域(scope)是指变量在程序中的可见性和生存期
4.1 全局作用域
- 定义:在所有函数外部声明的变量具有全局作用域。
- 可见性:在整个程序中可见,所有函数都可以访问。
- 生存期:从程序开始到结束。
int globalVar = 10; // 全局变量
void function() {
std::cout << globalVar; // 可以访问
}
4.2 局部作用域
- 定义:在函数或代码块内部声明的变量具有局部作用域。
- 可见性:仅在其声明的函数或代码块内部可见。
- 生存期:当控制流离开其作用域时,变量会被销毁。
void function() {
int localVar = 20; // 局部变量
std::cout << localVar; // 可以访问
}
// std::cout << localVar; // 错误:无法访问
4.3 块作用域
- 定义:在大括号
{}
内声明的变量具有块作用域。 - 可见性:仅在该块内部可见。
- 生存期:当控制流离开块时,变量被销毁。
void function() {
if (true) {
int blockVar = 30; // 块作用域变量
std::cout << blockVar; // 可以访问
}
// std::cout << blockVar; // 错误:无法访问
}
4.4 类作用域
- 定义:在类内部声明的变量具有类作用域。
- 可见性:在类的所有成员函数中可见,且在类的实例中可访问(通过对象)。
- 生存期:与类的实例一起存在。
class MyClass {
public:
int classVar; // 类成员变量
void display() {
std::cout << classVar; // 可以访问
}
};
4.5 命名空间作用域
- 定义:在命名空间内部声明的变量具有命名空间作用域。
- 可见性:在该命名空间内的所有函数可见。
- 生存期:从程序开始到结束,类似全局变量。
namespace MyNamespace {
int namespaceVar = 40; // 命名空间变量
}
void function() {
std::cout << MyNamespace::namespaceVar; // 可以访问
}
4.6 作用域优先级
- 局部作用域
- 块作用域
- 类作用域
- 命名空间作用域
- 全局作用域
4.7 作用域总结
作用域类型 | 可见性 | 生存期 | 示例 |
---|---|---|---|
全局作用域 | 在整个程序中可见 | 程序开始到结束 | int globalVar = 10; |
局部作用域 | 仅在函数或代码块内部可见 | 控制流离开作用域时被销毁 | void function() { int localVar = 20; } |
块作用域 | 仅在大括号内可见 | 控制流离开块时被销毁 | if (true) { int blockVar = 30; } |
类作用域 | 在类的所有成员函数中可见 | 与类的实例一起存在 | class MyClass { int classVar; }; |
命名空间作用域 | 在命名空间内可见 | 程序开始到结束 | namespace MyNamespace { int namespaceVar = 40; } |
5. 常量
常量是固定值,在程序执行期间不会改变。这些固定的值,又叫做字面量。
5.1 整数常量
整数常量可以是十进制、八进制或十六进制的常量。前缀指定基数:0x 或 0X 表示十六进制,0 表示八进制,不带前缀则默认表示十进制。
212 // 合法的
215u // 合法的
0xFeeL // 合法的
078 // 非法的:8 不是八进制的数字
032UU // 非法的:不能重复后缀
以下是各种类型的整数常量的实例:
85 // 十进制
0213 // 八进制
0x4b // 十六进制
30 // 整数
30u // 无符号整数
30l // 长整数
30ul // 无符号长整数
5.2 浮点常量
浮点常量由整数部分、小数点、小数部分和指数部分组成。您可以使用小数形式或者指数形式来表示浮点常量。
3.14159 // 合法的
314159E-5L // 合法的
510E // 非法的:不完整的指数
210f // 非法的:没有小数或指数
.e55 // 非法的:缺少整数或分数
5.3 布尔常量
- true 值代表真。
- false 值代表假。
我们不应把 true 的值看成 1,把 false 的值看成 0。
5.4 字符常量
字符常量是括在单引号中。如果常量以 L(仅当大写时)开头,则表示它是一个宽字符常量(例如 L’x’),此时它必须存储在 wchar_t 类型的变量中。否则,它就是一个窄字符常量(例如 ‘x’),此时它可以存储在 char 类型的简单变量中。
转义序列 | 含义 |
---|---|
\ | \ 字符 |
’ | ’ 字符 |
" | " 字符 |
? | ? 字符 |
\a | 警报铃声 |
\b | 退格键 |
\f | 换页符 |
\n | 换行符 |
\r | 回车 |
\t | 水平制表符 |
\v | 垂直制表符 |
\ooo | 一到三位的八进制数 |
\xhh . . . | 一个或多个数字的十六进制数 |
5.5 字符串常量
字符串字面值或常量是括在双引号 “” 中的。一个字符串包含类似于字符常量的字符:普通的字符、转义序列和通用的字符。
#include <iostream>
#include <string>
using namespace std;
int main() {
string greeting = "hello, runoob";
cout << greeting;
cout << "\n"; // 换行符
string greeting2 = "hello, \
runoob";
cout << greeting2;
return 0;
}
5.6 定义常量
在 C++ 中,有两种简单的定义常量的方式:
- 使用 #define 预处理器。
- 使用 const 关键字。
5.6.1 #define 预处理器
#define
是一种预处理器指令,通常用于定义宏常量。宏常量在编译时会被预处理器替换为相应的值。
语法
#define CONSTANT_NAME value
示例
#define PI 3.14159
#define MAX_SIZE 100
5.6.2 const 关键字
const
是 C++ 的一个关键字,用于声明常量。在 const
定义的常量中,类型是显式的,并且可以在编译时检查类型。
语法
const type CONSTANT_NAME = value;