C++是在C语言的基础上进行了扩展和加强的编程语言,除了最典型的OOP(允许开发者使用类和对象来组织和管理代码)和三大特性,还有一些特点和增强。
在C语言中,const
关键字用于声明只读(read-only)变量,但它的只读性在编译期间是不强制执行的。这意味着虽然您可以使用const
修饰一个变量,但仍然可以使用非const
指针去改变其值。这是C语言的一种弱约束。
const int x = 10;
int* ptr = (int*)&x; // 合法但不安全,ptr可以修改x的值
*ptr = 20; // x的值被修改了
而在C++中,const
关键字更为严格,它用于声明真正的常量。C++确保在编译期间对const
进行强制执行,这意味着你不能使用普通指针指向const
变量,也不能通过解引用方式间接修改其内容。只有使用const
修饰的指针才能指向const
变量。
const int x = 10;
const int* ptr = &x; // 合法,ptr是一个指向常量的指针
int* ptr2 = (int*)&x; // 非法,编译器将报错
*ptr2 = 20; // 非法,编译器将报错
(1)类型必须一致才能相互赋值(除了本身可以进行隐式转换的类型之间)
这是一种类型安全的规则,它确保了在赋值操作中,变量的数据类型必须匹配,除非涉及到可以进行隐式类型转换的情况。在C和C++中,类型必须明确,否则会引发编译器错误。例如,在C++中,不能将一个整数赋给一个字符串,除非进行适当的类型转换。
(2) C语言中重复定义多个相同名字的全局变量是合法的,但是C++不允许
这是C和C++之间的一个重要区别。在C语言中,可以在不同的源文件中多次定义相同名字的全局变量,编译器不会报错。这些全局变量在链接时会被合并。但是在C++中,这种操作是不允许的,会导致链接错误。C++要求每个全局变量只能定义一次,可以使用extern关键字来声明一个全局变量,然后在其他源文件中定义它。
说到全局变量的定义,那就不得不提一下关于在C中我们可以在同一个工程下任意定义多个全局变量。
// File1.c
#include
int globalVar = 42;
void printGlobalVar() {
printf("GlobalVar in File1.c: %d\n", globalVar);
}
// File2.c
#include
int globalVar = 100; // 重复定义同名的全局变量
void printGlobalVar() {
printf("GlobalVar in File2.c: %d\n", globalVar);
}
但是在C++中是允许的,C++举例如下:
// 在一个源文件中定义全局变量
int globalVar = 42;
// 在其他源文件中引用全局变量必须使用extern而不是再定义
extern int globalVar;
int main() {
// 使用全局变量
int x = globalVar;
return 0;
}
C语言中的枚举变量其实就是int,可以任意赋值,而C++的枚举变量只能赋值枚举值。
C++引入了强类型枚举(enum class)以增强对枚举类型的类型安全性和可读性。这是对C语言中传统枚举的增强。下面是C++中枚举增强的几个要点。
(1)强类型枚举(enum class): 强类型枚举引入了新的方式来定义枚举,它们在命名空间中创建了一个新的作用域,可以避免名称冲突,并且只能通过枚举的名称来访问枚举值。这提供了更好的类型安全性。
enum class Color {
Red,
Green,
Blue
};
Color myColor = Color::Red; // 强类型,只能通过Color::访问
(2)默认底层类型: 强类型枚举默认的底层类型是int
,但你可以显式指定底层类型。
enum class Day : char {
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
Sunday
};
(3)不会进行隐式类型转换: 强类型枚举不会隐式地转换为整数或其他类型,这减少了类型错误的可能性。
enum class Month {
January,
February,
March
};
int monthValue = static_cast(Month::January); // 需要显式类型转换
(4)枚举值作用域: 强类型枚举的值在其所属的枚举类的作用域内,不会污染全局命名空间。
enum class Animal {
Dog,
Cat
};
Animal pet = Animal::Dog; // Animal是Animal枚举类的一部分
在C++中,三目运算符(也称为条件运算符) ? :
用于根据条件选择执行不同的操作。与C语言类似,但与C语言不同的是,C++允许三目运算符的结果作为左值,这意味着你可以将其结果赋值给一个变量。这种特性在某些情况下可以帮助编写更简洁的代码。
int a = 5;
int b = 10;
int result = (a > b) ? a : b; // 如果a > b,将a赋值给result,否则将b赋值给result
C语言的struct 定义一组变量的集合,C编译器并不认为这是一种新的类型,C++中的 struct 是一个新的类型的定义声明。
在C++中,struct和class都用于定义用户自定义数据类型,这是C语言中的struct的增强。尽管struct和class都可以用于定义类,但它们之间有一些关键的区别:
(1)默认的访问控制:
struct
中的成员默认是public
的,可以从任何地方访问。struct
和class
中的成员默认是private
的,除非明确指定为public
或其他访问修饰符
(2)成员函数:
struct
中不能包含成员函数。struct
和class
都可以包含成员函数,允许在类内定义方法来操作成员数据。(3)默认继承权限:
struct
不能用于继承。struct
和class
都可以用于继承,但默认继承权限有所不同。在class
中,继承默认是private
的,而在struct
中,继承默认是public
的。// C++中的struct
struct Person {
std::string name;
int age;
void printInfo() {
std::cout << "Name: " << name << ", Age: " << age << std::endl;
}
};
// 继承自Person的struct,默认继承是public
struct Student : Person {
int studentId;
};
int main() {
Person person;
person.name = "Alice";
person.age = 25;
person.printInfo(); // 可以调用成员函数
Student student;
student.name = "Bob";
student.age = 20;
student.studentId = 12345;
student.printInfo(); // 也可以调用Person的成员函数
return 0;
}
在这个示例中,我们演示了C++中的 struct
可以包含成员函数,可以用于继承,并且默认继承权限是 public
。这些特性使得C++中的 struct
在某些情况下更类似于class
,但仍然保留了一些不同之处,如默认访问权限。
C++中的布尔类型(bool
)用于表示逻辑值,即真(true
)或假(false
)。布尔类型通常用于条件判断和控制程序的执行流程。以下是C++中布尔类型的介绍:
布尔类型的声明: 在C++中,你可以声明一个布尔变量并将其初始化为true
或false
,也可以将其用作函数的返回类型或参数类型。
bool isTrue = true; // 声明一个布尔变量并初始化为true
bool isFalse = false; // 声明一个布尔变量并初始化为false
逻辑运算符: 布尔类型通常与逻辑运算符一起使用,例如&&
(逻辑与)、||
(逻辑或)和!
(逻辑非)。这些运算符用于组合和操作布尔值。
bool condition1 = true;
bool condition2 = false;
bool result1 = condition1 && condition2; // 逻辑与
bool result2 = condition1 || condition2; // 逻辑或
bool result3 = !condition1; // 逻辑非
标准库: C++标准库中提供了一些与布尔类型相关的函数和类,例如
头文件中的std::boolalpha
操纵器,可以更改std::cout
的输出格式以显示true
和false
,而不是整数值1和0。
#include
using namespace std;
int main() {
bool myBool = true;
cout << boolalpha << myBool << endl; // 输出 "true",而不是 "1"
return 0;
}
C++中的动态内存分配是一种非常重要的特性,用于在运行时动态分配和释放内存。下面对C++中的动态内存分配(new/delete)进行总结:
1. 对比C和C++:
malloc()
和free()
函数来进行动态内存分配和释放。这些是函数。new
和delete
关键字,用于动态内存的分配和释放。2. 注意事项:
new
分配内存后,务必使用delete
释放相应的内存,以避免内存泄漏和多次释放。malloc
与delete
或new
与free
交叉使用,必须保持一致,以免出现未定义行为。new
和delete
关键字的主要用途是在处理类对象指针时进行内存的动态分配和释放。3. 使用语法:
使用new分配内存:使用new
关键字来动态分配内存,并返回指向分配内存的指针。
使用delete释放内存:使用delete
关键字来释放之前分配的内存。
类型* 指针名 = new 类型;
delete 指针名;
int* myInt = new int; // 分配一个整数的内存
*myInt = 42; // 向该内存写入值
delete myInt; // 释放分配的内存
更多C/C++语言、Linux系统、数据结构和ARM板实战相关文章,关注专栏:
手撕C语言
玩转linux
脚踢数据结构
系统、网络编程
探索C++
6818(ARM)开发板实战
一键三连喔
~