学习目标:
学习c++面向对象知识点
第2章 简单程序设计
1.类型别名:
typedef double Area;
using Area = double;
第3章 函数
1.main函数中可以有形参,被称为命令行参数。
2.函数可以直接或间接地保存自身,称为递归调用。
3.函数的参数传递:形参与实参结合的过程。方式有值传递与引用传递。
值传递:给形参分配内存空间,并用实参来初始化形参。这一过程是参数值的单相传递过程,一旦形参获得值后便与实参脱离关系。
引用传递:让形参可以影响实参。引用是一种特殊类型的变量,可以被认为是另一个变量的别名。一个引用从诞生时就必须确定是哪个变量的别名,而且始终为这个变量的别名,不可改变。
典例:交换(swap)的实现。
4.内联函数:用于功能简单且频繁使用的函数,关键字inline。不是在调用时发生控制转移,而是在编译时将函数体嵌入在每一个调用中。存在对自身调用的函数不可内联。
5.带默认形参值的函数:有默认值的形参必须在形参列表的最后。
例如:int add(int x = 1,int y),错误。
6.函数重载:具有相同的函数名,但是形参的个数或者类型不同。
注:形参必须不同:个数或类型不同。编译器不以形参名和返回值区分函数。
第四章 类与对象
1.面向对象基本特点:抽象,封装,继承,多态。
抽象:对具体问题(对象)进行概括,抽出一类对象的公共性质并加以描述的过程。分为数据抽象和行为抽象。
封装:将数据和操作数据的方法捆绑在一起,形成一个独立的单元。这个单元对外部隐藏了实现细节,只提供对外部可见的接口。
继承:是一种通过使用已存在的类(父类)创建新类(子类)的机制。子类继承了父类的属性和方法,同时可以添加新的属性和方法或者修改已有的方法。
多态:一段程序能够处理多种类型对象的能力。包括强制多态,重载多态,类型参数化多态以及包含多态。
2.类与对象的关系:类是对逻辑上相关的函数与数据的封装,是对问题的抽象描述,描述了一类问题的特征。而对象是类的实例化,具体体现了这些特征。总之,类定义了对象的结构和行为,而对象是类的具体表现。
3.内联成员函数:包括隐式声明(函数体直接放在类体内)和显式声明(函数体实现时,前面 加上关键字inline,类体中不加入函数体)。
4.构造函数:
(1)构造函数在对象被创建时自动调用。
(2)调用时无需提供参数的构造函数称为默认构造函数。若类中没有写构造函数,会自动生成一个隐含的构造函数(参数列表和函数体皆为空)。但注意,一旦自己定义了其他类的构造函数,系统将不会生成默认构造函数,因此最好还要自己定义默认构造函数。
(3)作为成员函数,构造函数可以直接访问类的所有数据成员,可以内联、带参数列表、带默认形参值、重载。
(4)委托构造函数:委托构造函数是一种允许一个构造函数调用同一类中的其他构造函数的机制。顺序:受委托的构造函数的初始值列表和函数体依次执行,然后控制权才会还给委托者函数。
class MyClass {
public:
// 主要构造函数
MyClass(int value) {
// 执行一些初始化逻辑
}
// 委托构造函数,调用主要构造函数
MyClass() : MyClass(42) {
// 可以在这里添加额外的初始化逻辑
}
};
(5)复制构造函数:形参是本类对象的引用,其作用是使用一个已经存在的对象,去初始化同类的一个新对象。
3种情况下复制构造函数被调用:
当用类的一个对象去初始化该类的另一个对象时;
MyClass obj1; // 调用默认构造函数
MyClass obj2 = obj1; // 调用复制构造函数
如果函数的形参是类的对象,调用函数时,进行形参和实参结合时(即当对象作为函数参数按值传递时,会调用复制构造函数来创建一个新的对象,该对象与原始对象相同);
void someFunction(MyClass param) {
// 复制构造函数在这里被调用
}
MyClass obj;
someFunction(obj); // 作为参数传递,调用复制构造函数
函数的返回值是类的对象,函数执行完成后返回调用者时。
MyClass createObject() {
MyClass obj;
return obj; // 调用复制构造函数,创建返回的对象的副本
}
MyClass newObj = createObject();
(6)析构函数:
析构函数(Destructor)是在对象生命周期结束时被调用的特殊函数,用于释放对象所占用的资源、执行清理操作或者进行其他必要的收尾工作。析构函数的名称与类名相同,前面加上一个波浪号(~
)。
以下是关于析构函数的一些重要概念:
语法:
-
析构函数的语法如下:
class MyClass { public: // 构造函数 MyClass() { // 构造逻辑 } // 析构函数 ~MyClass() { // 析构逻辑 } };
调用时机:
- 析构函数在对象的生命周期结束时自动被调用,通常是在对象超出其作用域、被删除或程序终止时。
- 对于动态分配的对象(通过
new
操作符创建的对象),析构函数会在调用delete
时被调用。
资源释放和清理:
- 析构函数常用于释放动态分配的内存、关闭文件、释放网络连接等资源的清理工作。
- 在析构函数中执行必要的清理操作有助于避免资源泄漏和确保程序的健壮性。
默认析构函数:
- 如果用户没有显式定义析构函数,编译器会生成一个默认的析构函数,它执行基本的对象销毁工作。对于大多数情况,编译器生成的默认析构函数是足够的。
注意事项:
- 在析构函数中应该谨慎地处理资源释放和清理逻辑,确保不会引起不必要的问题。
- 不要在析构函数中抛出异常,因为在 C++ 中,析构函数不允许抛出异常。
- 析构函数不接收任何参数,但可以是虚函数。
- 函数体为空的析构函数未必不做任何事情。
(6)移动构造函数:
移动构造函数(Move Constructor)是C++11引入的一项特性,用于在对象之间进行资源的转移,从而提高性能。移动构造函数通常用于移动语义(Move Semantics)的实现,通过移动而非拷贝来传递资源的所有权,避免不必要的资源复制。移动构造函数的语法如下:
class MyClass {
public:
// 移动构造函数
MyClass(MyClass&& other) noexcept {
// 执行资源的转移和其他必要的操作
// 注意:noexcept 关键字用于标识此函数不抛出异常
}
};
右值引用参数:
- 移动构造函数的参数是一个右值引用(&&),表示它接受的是将要被移动的对象。
资源转移:
- 移动构造函数的主要目的是将资源(如动态分配的内存)从一个对象移动到另一个对象,而不是拷贝。
性能提升:
- 移动构造函数的引入主要是为了提高性能。在某些情况下,通过移动资源而不是拷贝资源可以避免不必要的开销。
noexcept 关键字:
- 移动构造函数通常使用
noexcept
关键字,以标识该函数不抛出异常。这对于一些标准库和编译器的优化是有帮助的。
与拷贝构造函数的区分:
- 移动构造函数与拷贝构造函数在参数类型上有所区别,以确保在编译器可以明确选择调用哪一个。
示例:
#include <iostream>
class MyResource {
public:
// 移动构造函数
MyResource(MyResource&& other) noexcept {
// 执行资源的转移和其他必要的操作
std::cout << "Move Constructor called." << std::endl;
}
};
int main() {
MyResource obj1;
MyResource obj2 = std::move(obj1); // 移动构造函数被调用
return 0;
}
在上述示例中,通过 std::move
将 obj1
转换为右值引用,触发了移动构造函数的调用,实现了资源的高效转移。
5.default与delete函数:
在C++中,default
和 delete
是用于特殊成员函数(特别是构造函数和析构函数)的关键字,用于显式指定编译器生成或禁止生成某个特殊成员函数。
default
关键字:
-
default
用于指示编译器生成默认实现的特殊成员函数。这通常用于在类的定义中,显式声明需要默认实现的特殊成员函数。例如:class MyClass { public: // 使用 default 指示编译器生成默认构造函数 MyClass() = default; // 使用 default 指示编译器生成默认析构函数 ~MyClass() = default; // 默认拷贝构造函数 MyClass(const MyClass& other) = default; // 默认拷贝赋值运算符 MyClass& operator=(const MyClass& other) = default; };
-
上述代码中,
MyClass
显式指示编译器生成了默认的构造函数、析构函数、拷贝构造函数和拷贝赋值运算符。
delete
关键字:
-
delete
用于禁止编译器生成某个特殊成员函数,或者禁止使用某个特殊成员函数。这通常用于删除类的拷贝构造函数和拷贝赋值运算符,以防止对象被拷贝。例如:class NoCopyClass { public: // 禁止拷贝构造函数 NoCopyClass(const NoCopyClass&) = delete; // 禁止拷贝赋值运算符 NoCopyClass& operator=(const NoCopyClass&) = delete; };
-
上述代码中,
NoCopyClass
显式使用delete
关键字,禁止了拷贝构造函数和拷贝赋值运算符。
这两个关键字提供了更多的控制权,允许程序员明确指定或禁用某些特殊成员函数的生成。 default
通常用于启用默认实现,而 delete
通常用于禁用某个成员函数。
6.类的组合:一个类内嵌其他类的对象作为成员,关系是包含与被包含。
构造函数的调用顺序:
调用内嵌对象的构造函数(顺序为按照内嵌对象在类定义声明的次序,注意,内嵌对象在构造函数的初始化列表中出现的顺序与内嵌对象构造函数的调用顺序无关)---------->执行本类构造函数的函数体
7.结构体与类的唯一区别:类默认访问控制属性为private;结构体默认访问控制属性为public。
8.联合体:其全部数据成员共享一组内存单元。因此给一个成员赋值后,其他成员的值可能会变得无效。
(1)不能继承,不支持包含多态。
(2)一般只用来存储公有数据,而不定义函数成员。
9.枚举:
在C++中,enum
(枚举)是一种用于定义命名整数常量的数据类型。通过使用enum
,你可以为一组相关的整数值创建一组符号名称,使代码更具可读性。
以下是一个简单的枚举的定义:
#include <iostream>
// 声明一个枚举类型
enum Color {
RED, // 0
GREEN, // 1
BLUE // 2
};
int main() {
// 声明一个枚举变量
Color myColor = RED;
// 使用枚举值
if (myColor == RED) {
std::cout << "The color is red." << std::endl;
} else if (myColor == GREEN) {
std::cout << "The color is green." << std::endl;
} else if (myColor == BLUE) {
std::cout << "The color is blue." << std::endl;
}
return 0;
}
在这个例子中,Color
是一个枚举类型,它包含了三个枚举值:RED
,GREEN
,和 BLUE
。这些值被赋予默认的整数值,从0开始。你也可以显式指定每个枚举值的整数值,例如:
enum Color {
RED = 10,
GREEN = 20,
BLUE = 30
};
这里,RED
的值是10,GREEN
的值是20,BLUE
的值是30。
注意一些关于枚举的特性:
默认整数值: 如果没有显式指定整数值,第一个枚举值默认为0,后续的枚举值在前一个的基础上递增。
枚举变量的赋值: 你可以将枚举值赋给相应的枚举变量,也可以直接将整数值赋给枚举变量。
枚举作用域: 枚举值在定义时是在同一个作用域中的,但你可以使用enum class
来引入枚举的作用域。
enum class Status {
OK,
ERROR
};
Status myStatus = Status::OK;
enum class
引入了更严格的类型安全性,防止枚举值的隐式转换。
枚举在编程中常用于提高代码可读性,使代码更易于理解和维护。