资料来源:南科大 于仕琪 C/C++ Program Design
LINK:CPP/week09 at main · ShiqiYu/CPP · GitHub
一、本节内容
本节首先回顾了类的相关基本概念。
本节LAB练习部分主要为创建一个简单的类,包括:访问private成员、修改Const数据成员、修改Const函数中的数据成员、初始化Const数据成员。
1.1 构造函数和析构函数 Constructor and destructor
1.1.1 类的构造函数 Class constructor
构造函数是特殊的成员函数:
1. 与类名完全相同
2. 无返回值
3. 它是类的公共成员函数
4. 在创建该类的对象时调用
- 成员初始化列表通过冒号与参数列表区分开来。它是一个逗号分隔的列表,其中要分配给成员的值放在成员名称后面的括号中
- 成员初始化列表主要用于向成员类对象构造函数传递参数
1.1.2 默认构造函数 Default constructor
- 默认构造函数是在不提供显式初始化值时用于创建对象的构造函数。如果不提供任何构造函数,编译器将自动提供一个默认构造函数。它是默认构造函数的隐式版本,不做任何事情。
- 一个类中只有一个默认构造函数。
1.1.3 创建对象 Creating objects
- 创建对象时,将自动调用构造函数。如果定义了默认构造函数,则可以声明对象变量而无需显式初始化它们。
- 注意不要被非默认构造函数的隐式形式所误导。当隐式调用默认构造函数时,不要使用括号
1.1.4 类的析构函数 Class Destructors
析构函数也是一个特殊的成员函数:
1.析构函数名与类名相同,但以波浪号(~)开头。
2. 析构函数没有返回值。
3. 析构函数没有参数。
4. 一个类中只能有一个析构函数。
5. 如果没有为类提供默认析构函数,编译器总是会创建一个默认析构函数。
6. 当对象超出作用域或将删除应用于指向该对象的指针时调用。
1.2 静态成员变量和静态成员函数 Static member variables and static member functions
- 类中的静态成员变量由所有类对象共享
- 静态成员变量的定义看起来像对象的全局定义,只是它的名称用类作用域操作符限定::
- 注意:静态变量必须在类外进行定义/初始化
- 静态成员函数可以通过这种方式独立于类对象调用。
- 只有当成员函数不访问任何非静态类成员时,才能将其声明为静态函数。
- 通过在类定义中使用关键字static作为其声明的前缀,使其成为静态的
1.3 常数成员变量与常数成员函数 Const member variables and const member functions
- const关键字指定变量的值为常量,并告诉编译器阻止程序员修改它。如果某些成员变量不需要修改,则可以将这些变量定义为const。这些const成员变量可以通过构造函数中的初始化列表进行初始化。
- const修饰符跟在函数的形参表后面,这样的函数称为const成员函数。cconst表示类的数据不会被函数修改。
- 在类体外部定义的const成员函数必须在声明和定义中指定const修饰符。
1.4 this 指针
二、习题笔记
习题1
问题:
- 静态成员变量
num
没有在类外进行定义。可以在类外定义静态成员变量num
。 - 如果希望
display()
函数可以被Demo
类直接调用而不是通过Demo
类的对象调用,可以将display()
函数声明为静态函数。
代码:
#include <iostream>
using namespace std;
class Demo
{
public:
static int num;
static void display()
{
cout << "The value of the static member variable num is: " << num << endl;
}
};
// 在类外定义静态成员变量
int Demo::num = 0;
int main()
{
// 直接通过类名调用静态成员函数
Demo::display();
return 0;
}
习题2
程序解析:
- 成员变量:
m_a
是一个const
整型变量,这意味着它一旦被初始化,就不能再被修改。 - 构造函数:
ConstMember(int a) : m_a(a) {}
使用初始化列表来初始化m_a
。这是唯一可以初始化const
成员变量的地方。 - 成员函数:
void display() const
是一个常量成员函数,表示它不会修改类的任何成员变量。它输出m_a
的值
运行结果:
如果取消掉注释,程序将会报错。原因是m_a
是一个 const
成员变量,不能在对象创建后被修改。
习题3
- main.cpp
#include "complex.hpp"
int main()
{
// 使用默认参数创建复数对象
Complex c1;
Complex c2(1.0, 2.0);
// 显示复数
cout << "c1: ";
c1.display();
cout << "c2: ";
c2.display();
// 复数加法
Complex c3 = c1.add(c2);
cout << "c1 + c2: ";
c3.display();
// 复数减法
Complex c4 = c1.subtract(c2);
cout << "c1 - c2: ";
c4.display();
return 0;
}
- complex.hpp
#pragma once
#include <iostream>
using namespace std;
class Complex
{
private:
double realPart;
double imaginaryPart;
public:
Complex() : realPart(0.0), imaginaryPart(0.0) {}
Complex(double real, double imaginary) : realPart(real), imaginaryPart(imaginary) {}
// 加法运算
Complex add(const Complex &other) const
{
return Complex(realPart + other.realPart, imaginaryPart + other.imaginaryPart);
}
// 减法运算
Complex subtract(const Complex &other) const
{
return Complex(realPart - other.realPart, imaginaryPart - other.imaginaryPart);
}
// the declarations, the definitions are out of the class
// 显示复数
void display();
};
- complex.cpp
#include "complex.hpp"
void Complex::display()
{
cout << realPart;
if (imaginaryPart >= 0)
cout << " + " << imaginaryPart << "i" << endl;
else
cout << " - " << -imaginaryPart << "i" << endl;
}
Tips:
- 在类外定义成员函数时,一定要在函数前面加上 Complex:: 否则就只是普通函数。
- 在定义构造函数时,有两种初始化方法:
// 使用初始化列表的构造函数
Complex() : realPart(0), imaginaryPart(0) {}
Complex(double real, double imaginary) : realPart(real), imaginaryPart(imaginary) {}
// 带有默认参数的构造函数
Complex(double real = 0.0, double imaginary = 0.0) : realPart(real), imaginaryPart(imaginary) {}
//由于成员变量均为double,因此初始化时写为0.0较为合适
- 由于计算过程中并不需要更改原数据,使用函数引用更为高效。