[C++ Basic] User-Defined Types: Class
1. Class 基础概念
定义与创建:
介绍如何定义类,包括类的成员变量和成员函数。
1 | class ClassOne |
- 提供简单的例子,例如如何定义类并创建对象。
1 | // 直接使用类名创建对象 |
访问控制:
解释 public
, private
, protected
的作用。
- 示例:类的成员如何通过这些访问控制符来限制访问权限。
class后面的semicolon分号
C++ 的分号事告诉编译器你的实例的对象列表,常见:变量(包括函数变量)函数末尾就不需要写。class由于后面可以写实例,所以需要写分号
2. 构造函数与析构函数
构造函数是类的一种特殊的成员函数,它会在每次创建类的新对象时执行。构造函数的名称与类的名称是完全相同的,并且不会返回任何类型,也不会返回 void。构造函数可用于为某些成员变量设置初始值。
析构函数是类的一种特殊的成员函数,它会在每次删除所创建的对象时执行。析构函数的名称与类的名称是完全相同的,只是在前面加了个波浪号(~)作为前缀,它不会返回任何值,也不能带有任何参数。析构函数有助于在跳出程序(比如关闭文件、释放内存等)前释放资源。
3. 类的成员函数
- 普通成员函数:如何在类中定义和使用普通的成员函数。
- 提供类内和类外定义成员函数的例子。
- 常量成员函数:解释
const
成员函数的意义,即该函数不会修改对象的成员变量。 - 静态成员与静态函数:解释
static
成员变量和函数,以及它们的使用场景。
函数重载
class内的对象的引用
a.b
is only used ifb
isa
member of the object实例 (or reference to an object) a. So fora.b
,a
will always be an actual object (or a reference to an object) of a class.a->b
is, originally, a shorthand notation for(*a).b
.- However,
->
is the only of the member access operators that can be overloaded, so if a is an object of a class that overloads operator-> (common such types are smart pointers and iterators), then the meaning is whatever the class designer implemented.
- However,
- To conclude:
- With a->b, if a is a pointer, b will be a member of the object the pointer a refers to.
- If, however, a is an object of a class that overloads this operator, then the overloaded operator function
operator->()
gets invoked.
注意不只对变量还有函数
1 | Trie *tree = new Trie(); |
3.5 继承
- C++中的继承是一种面向对象编程的重要概念,它允许一个类(称为派生类或子类)从另一个类(称为基类或父类)继承属性和行为。
- 继承允许在基类的基础上构建更具体和特殊化的派生类,从而实现代码重用、层次化和多态性。
C++中的继承通过以下语法来定义:
1 | class DerivedClass : access-specifier BaseClass { |
其中,DerivedClass是派生类的名称,BaseClass是基类的名称,access-specifier
是访问控制符,可以是public、protected或private。
继承有以下几种类型, 由access-specifier
控制:
- 公有继承(public inheritance):通过public继承,
- 基类的公有成员在派生类中仍然是公有的,保留其访问权限。
- 基类的保护成员在派生类中变为保护的,
- 私有成员在派生类中不可直接访问。
- 保护继承(protected inheritance):通过protected继承,
- 基类的公有和保护成员在派生类中都变为保护的,
- 私有成员在派生类中不可直接访问。
- 私有继承(private inheritance):通过private继承,
- 基类的公有和保护成员在派生类中都变为私有的,
- 私有成员在派生类中不可直接访问。
- 默认情况下,如果不显式指定继承类型,则使用的是私有继承(private inheritance)
- 但是如果基类使用struct关键字定义并且未指定访问控制修饰符,则默认继承类型为公有继承。
1 | struct BaseStruct { |
- 通过继承,派生类可以访问并重用基类的成员变量和成员函数。
- 派生类还可以添加自己的成员变量和成员函数,从而扩展基类的功能。
- 此外,派生类还可以覆盖(override)基类的成员函数,以实现多态性。
- 继承还支持多层次(多级)继承,其中一个派生类可以作为另一个派生类的基类。
继承是面向对象编程中的重要概念,它提供了代码的组织结构和灵活性。通过继承,可以构建更具层次结构和复杂性的类体系,并实现代码重用和多态性。
4. 虚函数与多态
- 虚函数的定义:讲解什么是虚函数,如何使用
virtual
关键字定义虚函数。- 解释多态性的概念,以及基类指针或引用如何调用派生类的函数。
- 提供一个简单的虚函数示例。
- 纯虚函数与抽象类:进一步介绍如何定义抽象类及其在设计模式中的应用。
- 提供纯虚函数和抽象类的实际例子。
虚函数
- 虚函数(Virtual Function)可以实现 动态多态
- 在基类中使用 virtual 关键字将函数声明为虚函数,并在派生类中重新定义(override)这些虚函数,派生类中重新定义时也可以使用 virtual 修饰符,但不是必需的。
1 | class Geometry{ |
多态
- 动态多态:虚函数实现为主,性能会有一定损耗. Ref
- 静态多态:模版函数为主
1 | template<typename Geometry> |
5. 拷贝构造与赋值操作
- 拷贝构造函数:介绍什么是拷贝构造函数,如何定义,以及其用途(例如深拷贝)。
- 赋值操作符重载:说明如何重载赋值操作符
operator=
,以及它与拷贝构造函数的区别。
拷贝和浅拷贝的区别
(举例说明深拷贝的安全性)
- 当出现类的等号赋值时,会调⽤拷贝函数,在未定义显示拷贝构造函数的情况下, 系统会调⽤默认的拷贝函数-即浅拷贝(两类中的两个指针指向同⼀个地址),它能够完成成员的⼀⼀复制。当数据成员中没有指针时,浅拷贝是可⾏的。
- 但当数据成员中有指针时,如果采⽤简单的浅拷贝,则两类中的两个指针指向同⼀个地址,当对象快要结束时,会调⽤两次析构函数,⽽导致指野指针的问题。
- 注意所有new的变量,需要在Destructors里显示delete
6. 动态内存管理与RAII
- 介绍如何在类中管理动态分配的内存,并介绍 RAII(资源获取即初始化)的概念。
- 示例:如何使用智能指针(如
std::unique_ptr
)来管理资源,以避免内存泄漏。
7. 其他高级特性
友元函数与友元类
在 C++ 中,friend
关键字用来允许某些特定的函数或类访问另一个类的私有(private
)或受保护(protected
)成员。这是一个重要的特性,因为它可以让其他类或函数绕过常规的访问控制规则,这在某些特定的设计场景中非常有用。
使用 friend
的情景
- 增强封装:有时,两个或多个类协同工作得很密切,而你又不想为了一个类访问另一个类的内部成员而公开这些成员。
- 实现操作符重载:例如,重载输入输出操作符时,通常会需要访问类的私有数据。
注意事项
- 破坏封装:过度使用
friend
关键字可能会破坏封装和隐藏的原则,使得代码维护和理解变得更加困难。 - 设计决策:通常,如果发现需要大量使用
friend
关键字,这可能是需要重新考虑你的设计的信号。
使用 friend
关键字时应谨慎,确保其真正必要且有助于代码的清晰和功能的实现。
运算符重载:
简单介绍如何对类进行运算符重载,如 +
,==
等。
重载运算符和重载函数
C++ 允许在同一作用域中的某个函数和运算符指定多个定义,分别称为函数重载和运算符重载。
重载声明是指一个与之前已经在该作用域内声明过的函数或方法具有相同名称的声明,但是它们的参数列表和定义(实现)不相同。
当您调用一个重载函数或重载运算符时,编译器通过把您所使用的参数类型与定义中的参数类型进行比较,决定选用最合适的定义。选择最合适的重载函数或重载运算符的过程,称为重载决策。
override关键字作用
如果派生类在虚函数声明时使用了override描述符,那么该函数必须重载其基类中的同名函数,否则代码将无法通过编译。
8. 总结与最佳实践
- 总结 C++ 类的设计和使用中的最佳实践,强调使用构造函数、析构函数、拷贝构造函数和虚函数时的注意事项。
- 提供一些常见的 C++ 编程模式和建议。
单例配置类
参考文献
[C++ Basic] User-Defined Types: Class
http://icarus.shaojiemike.top/2024/09/12/Work/Programming/2-languageGrammar/c/Class/