当前位置: 首页 > article >正文

C++11QT复习(二)

文章目录

    • Day4-4 New 与 delete 表达式(2025.03.20)
      • 1. `new` 表达式的三个步骤
      • 2. `delete` 表达式的两个步骤
      • 3. `new[]` 与 `delete[]`
    • Day5 类的定义和关键字再探(2025.03.24)
      • 1. C++ 关键字 `const`、`static`、`extern`
      • 2. 类的定义:Circle 和 Rect
      • 3. 完整代码
    • Day5-1 运算符重载(2025.03.24)
      • 1. 复数类 `Complex` 及其运算符重载
      • 2. 运算符重载的几种方式
      • 3. 关键区别
      • 4.完整代码

Day4-4 New 与 delete 表达式(2025.03.20)

在 C++ 中,newdelete 是用于动态内存管理的关键字。它们分别用于在堆上分配和释放对象或数组。

1. new 表达式的三个步骤

  1. 调用 operator new 标准库函数

    • operator new 负责在堆上申请一块原始的、未初始化的内存空间,以便存储对象。
    • 如果申请失败,会抛出 std::bad_alloc 异常(除非使用 nothrow 版本的 new)。
  2. 调用构造函数

    • 在申请到的内存空间上调用构造函数,初始化对象的数据成员。
  3. 返回指针

    • 返回指向新分配对象的指针,以供程序使用。

示例代码:

class A {
public:
    A() { cout << "A() constructor" << endl; }
    ~A() { cout << "~A() destructor" << endl; }
};

int main() {
    A* p = new A;  // 调用 operator new 申请内存 -> 调用构造函数 -> 返回指针
    delete p;      // 调用析构函数 -> 调用 operator delete 释放内存
    return 0;
}

2. delete 表达式的两个步骤

  1. 调用析构函数

    • 在释放对象所占的内存前,先执行析构函数,以回收对象的数据成员所占用的资源(如动态分配的内存、文件句柄等)。
  2. 调用 operator delete 库函数

    • 释放对象本身所占用的内存空间,使其可被重新分配。

示例代码:

A* p = new A;
delete p; // 先调用析构函数,再释放内存

3. new[]delete[]

  • new[] 用于动态分配对象数组,必须使用 delete[] 释放。
  • delete 只能释放单个对象,而 delete[] 释放的是整个数组。
A* arr = new A[5];  // 申请 5 个对象的数组

delete[] arr;       // 释放数组

如果用 delete 释放 new[] 申请的数组,可能会导致未完全析构的对象泄漏。


Day5 类的定义和关键字再探(2025.03.24)

1. C++ 关键字 conststaticextern

const int global_a = 10;  // 只读常量
static int s_b = 10;      // 静态全局变量(仅限当前文件可见)
extern int SIZE = 10;     // 外部变量(多个文件可共享)
  • const:用于定义只读变量,防止意外修改。
  • static:修饰局部变量时,延长变量生命周期,修饰全局变量时,限制其作用域。
  • extern:用于声明外部变量,使其可以在多个文件中访问。

示例:

void test() {
    static int fun_c = 0;  // 仅初始化一次,生命周期贯穿整个程序
    fun_c++;
    cout << "fun_c = " << fun_c << endl;
}

2. 类的定义:Circle 和 Rect

class Circle {
public:
    Circle(double r = 0) : _r(r) {
        cout << "Circle()" << endl;
    }
    
    ~Circle() {
        cout << "~Circle()" << endl;
    }

    double getArea() const {
        return M_PI * _r * _r;
    }

private:
    double _r;
};

要点:

  • 构造函数(Constructor): 负责初始化对象,可以带默认参数。
  • 析构函数(Destructor): 负责清理资源,名称前带 ~
  • 成员函数(Member Function): const 关键字保证不会修改对象数据。

3. 完整代码

#define _USE_MATH_DEFINES
#include <iostream>
#include <cmath>

using namespace std;
//关键字
//const
const int global_a = 10;
//static
static int s_b = 10;
//extern
extern int SIZE  = 10;
//三者的用途:const 修饰常量,static 修饰全局变量,extern 修饰外部变量

void test()
{
	int local_v = 0;
	static int fun_c;//静态局部变量 可以延长变量的生命周期
	fun_c++;
	cout << "local_v = " << " " << local_v << " ," << "fun_c = " << " " << fun_c << endl;
}

//定义一个圆
class Circle
{
public:
	Circle(double r = 0)
		: _r(r)
	{
		cout << "Circle(double r = 0)" << endl;
	}

	Circle(double r,char* name)
		: _r(0)
		, _name(new char[strlen(name) + 1])
	{
		strcpy_s(_name, strlen(name) + 1,name);
		cout << "Circle(double r = 0)" << endl;
	}
	~Circle()
	{
		cout << "~Circle()" << endl;
	}

	double getRadius() const
	{
		return _r;
	}

	//setRadius
	void setRadius(double r)
	{
		_r = r;
	}

	double getArea() const
	{
		return M_PI * _r * _r;
	}

private:
	double _r;
	char* _name;
};

//定义一个矩形
class Rect
{
public:
	Rect(double l = 0, double w = 0)
		: _l(l)
		, _w(w)
	{
		cout << "Rect(double l = 0, double w = 0)" << endl;
	}
	~Rect()
	{
		cout << "~Rect()" << endl;
	}

private:
	double _l;
	double _w;
};

void testCircle()
{
	Circle c1(10);
	cout << "c1.getRadius() = " << c1.getRadius() << endl;
	cout << "c1.getArea() = " << c1.getArea() << endl;
	cout << endl << endl;
	Circle c2;
	c2.setRadius(20);
	cout << "c2.getRadius() = " << c2.getRadius() << endl;
	cout << "c2.getArea() = " << c2.getArea() << endl;
}

int main()
{
	test();
	test();
	test();
	cout << endl << endl;

	testCircle();
	return 0;
}

Day5-1 运算符重载(2025.03.24)

1. 复数类 Complex 及其运算符重载

class Complex {
    friend Complex operator*(const Complex& lhs, const Complex& rhs);
public:
    Complex(double r = 0, double i = 0) : _real(r), _imag(i) {}
    
    Complex operator-(const Complex& rhs) const {
        return Complex(_real - rhs._real, _imag - rhs._imag);
    }

    Complex& operator++() {  // 前置++
        ++_real;
        ++_imag;
        return *this;
    }

    Complex operator++(int) {  // 后置++
        Complex tmp(*this);
        _real++;
        _imag++;
        return tmp;
    }
    
    Complex& operator+=(const Complex& rhs) {
        _real += rhs._real;
        _imag += rhs._imag;
        return *this;
    }

    void display() const {
        cout << _real << " + " << _imag << "i" << endl;
    }

private:
    double _real;
    double _imag;
};

2. 运算符重载的几种方式

  • 成员函数重载(适用于 +=++-):

    Complex operator-(const Complex& rhs) const;
    Complex& operator++();
    Complex operator++(int);
    Complex& operator+=(const Complex& rhs);
    
  • 友元函数重载(适用于 +*):

    friend Complex operator+(const Complex& lhs, const Complex& rhs);
    friend Complex operator*(const Complex& lhs, const Complex& rhs);
    

3. 关键区别

运算符适用方式说明
+普通函数需要访问两个对象的数据,可用友元函数
-成员函数只需要访问当前对象数据
++成员函数影响当前对象,前置++返回引用,后置++返回值
*友元函数需要访问两个对象的数据

示例代码:

Complex c1(1, 2), c2(3, 4);
Complex c3 = c1 + c2;
c3.display();

总结:

  • 友元函数适用于二元运算(如 +*)。
  • 成员函数适用于一元运算(如 ++)和复合赋值运算(如 +=)。

4.完整代码

#include <iostream>
#include <limits.h>

using namespace std;

//复数
class Complex
{
	friend Complex operator*(const Complex& lhs, const Complex& rhs);
	//Complex operator/(const Complex& rhs) const;
public:
	Complex(double r = 0, double i = 0)
	: _real(r), _imag(i) 
	{
		cout << "Complex(double r = 0, double i = 0)" << endl;
	}

	~Complex()
	{
		cout << "~Complex()" << endl;
	}

	double getReal() const
	{
		return _real;
	}

	double getImag() const
	{
		return _imag;
	}

	//运算符重载之成员函数
	Complex operator-(const Complex& rhs) const
	{
		return Complex(_real - rhs._real, _imag - rhs._imag);
	}
	
	//自增运算符重载
	Complex& operator++() //前置++
	{
		++_real;
		++_imag;
		return *this;
	}

	//后置自增运算符重载
	Complex operator++(int) //后置++
	{
		Complex tmp(*this);
		_real++;
		_imag++;
		return tmp;//返回类型是一个临时对象,所以不适用引用类型
	}

	//前置++和后置++的区别?
	//解答:前置++返回是对象的引用,是左值可以取地址
	//后置++返回的是局部对象,是右值不能取地址
	
	//+=运算符重载
	//复合赋值运算符重载,推荐以成员函数的形式重载
	Complex& operator+=(const Complex& rhs)
	{
		_real += rhs._real;
		_imag += rhs._imag;
		return *this;
	}



	void display() const
	{
		
		if (_imag > 0)
		{
			cout << _real << " + " << _imag << "i" << endl;
		}
		else if (_imag == 0)
		{
			cout << _real << endl;
		}
		else
		{
			cout << _real << " - " << -_imag << "i" << endl;
		}
	}
private:
	double _real;
	double _imag;
};	

//“operator + ”必须至少有一个类类型的形参
//int operator+(int lhs, int rhs)
//{
//	//return _real + rhs;
//}

//运算符重载之普通函数
Complex operator+(const Complex& lhs, const Complex& rhs)
{
	return Complex(lhs.getReal() + rhs.getReal(), lhs.getImag() + rhs.getImag());
}


//运算符重载之友元函数(推荐使用)
Complex operator*(const Complex& lhs, const Complex& rhs)
{
	return Complex(lhs._real * rhs._real - lhs._imag * rhs._real,
		lhs._real * rhs._real + lhs._real * rhs._real);
}

void test()
{
	Complex c1(1, 2);
	cout << "c1 = ";
	c1.display();
	cout << endl << endl;

	Complex c2(3, 4);
	cout << "c2 = ";	
	c2.display();
	cout << endl << endl;

	Complex c3 = c1 + c2;
	cout << "c3 = c1 + c2 = ";
	c3.display();
}

void test2()
{
	Complex c1(1, 2);
	cout << "c1 = ";
	c1.display();
	cout << endl << endl;
	Complex c2(3, 4);
	cout << "c2 = ";	
	c2.display();
	cout << endl << endl;

	Complex c3 = c1 - c2;
	cout << "c3 = c1 - c2 = ";
	c3.display();

}

void test3()
{
	Complex c1(1, 2);
	cout << "c1 = ";
	c1.display();
	cout << endl << endl;
	Complex c2(3, 4);
	cout << "c2 = ";
	c2.display();
	cout << endl << endl;
	Complex c3 = c1 * c2;
	cout << "c3 = c1 * c2 = ";
	c3.display();

	c3 += c1;
	cout << "c3 += c1 = ";
	c3.display();

	
}

void test4()
{
	Complex c3(4, 6);
	cout << "c3 = ";
	c3.display();
	cout << endl << endl;
	++c3;
	cout << "++c3 = ";
	c3.display();

	cout << endl << endl;
	c3++;
	cout << "c3++ = ";
	c3.display();

	Complex c4(4, 6);
	cout << "c4 = ";
	c4.display();
	c4++;
	cout << "c4++ = ";
	c4.display();
	cout << "前置++返回是对象的引用,是左值可以取地址,后置++返回的是局部对象,是右值不能取地址";
}

int main(int argc, char*  argv[])
{
	//test();
	//test2();
	//test3();
	test4();
	return 0;
}

http://www.kler.cn/a/612523.html

相关文章:

  • kafka 如何保证消息不丢失,详细讲解
  • docker-Dify外接Fastgpt知识库
  • python dict转换成json格式
  • 【C++游戏引擎开发】《线性代数》(2):矩阵加减法与SIMD集成
  • PHP 应用SQL 注入符号拼接请求方法HTTP 头JSON编码类
  • 鸿蒙 ArkUI 进行网络状态监听封装
  • vector和list区别
  • leetcode240.搜索二维矩阵||
  • Flask接口开发--引入mysql
  • Qt:QWebEngineView显示网页失败
  • Android 底部EditView输入时悬浮到软键盘上方
  • 无人机产教融合新方向,装调检修技术详解
  • 前缀和、差分
  • C语言--文件操作教案
  • Mybatis缓存模块分析-源码
  • C# SerialPort 类中清空缓存区的方法
  • 如何使用腾讯云HAI快速、高质量生成Stable Diffusion图片
  • vmwaretools解压失败|vmware tools distrib cannot mkdir read only file system|bug汇总
  • 2025年渗透测试面试题总结-某奇安信-Ateam(题目+回答)
  • Oracle初识:登录方法、导入dmp文件