重学C++ 重构C++知识体系

C++基础容器

序列型容器–数组

◆ 概念

  • 代表内存里一组连续的同类型存储区

  • 可以用来把多个存储区合并成一个整体

    比如:

    int arr[10] = {1,2,3,4,5,6,7,8};

◆ 数组声明

  • int arr[10]
  • 类型名称int表示数组里所有的元素的类型
  • 名称arr是数组的名称
  • 整数10表示数组里包含的元素个数
  • 数组元素个数不可变

新型数组–vector

◆ Vector 是面向对象方式的动态数组

向量(Vector)是一个封装了动态大小数组的顺序容器(Sequence Container)。跟任意其它类型容器一样,它能够存放各种类型的对象。可以简单的认为,向量是一个能够存放任意类型的动态数组。

vector 可以完成动态扩容的过程

#include
using namespace std;
int main()
{

	vector<int> vec = { 1,2,3,4 };
	vec.push_back(5); # 在尾部进行元素插入操作
    return 0;
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z5dWlVHS-1591808470669)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

capacity 当前vector分配的大小

size 当前使用数据的大小

// vector_test.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include 
#include 
#include 
#include 
using namespace std;

int main()
{
	//顺序访问
	vector<int>obj;
	for (int i = 0; i<10; i++)
	{
		obj.push_back(i);
	}

	cout << "直接利用数组:";
	for (int i = 0; i<10; i++)//方法一 
	{
		cout << obj[i] << " ";
	}

	cout << endl;
	cout << "利用迭代器:";
	//方法二,使用迭代器将容器中数据输出 
	vector<int>::iterator it;//声明一个迭代器,来访问vector容器,作用:遍历或者指向vector容器的元素 
	for (it = obj.begin(); it != obj.end(); it++)
	{
		cout << *it << " ";
	}
	return 0;
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L5R5UpIN-1591808470671)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

字符串变量与常量

◆ 字符串变量

  • 字符串是以空字符(’\0’)结束的字符数组
  • 空字符 ‘\0’ 自动添加到字符串的内部表示中国
  • 在声明字符串变量时, 应该为这个空结束符预留一个额外元素的空间如:char strHelloWorld ={“Helloworld”};

◆ 字符串的指针表示方法

◆ 字符串的常见操作

  • 字符串长度 strlen(s)
  • 字符串比较: strcmp(str1,str2)
  • 字符串拷贝:strcpy(s1,s2) 复制字符串s2到s1
  • 复制指定长度字符串: strncpy(s1,s2,n)
  • 字符串拼接: strcat(str1,str2) 将字符串str2接到str1后边
  • 查找字符串: strchr(s1,ch)查找ch第一次出现的位置
  • 查找字符串:strstr(s1,s2)在s1里查找s2第一次出现的位置
#include "stdafx.h"
#include
#include
using namespace std;


int main()
{
    // 定义一个数组
	char strHelloWorld[11] = { "helloworld" }; 
	cout << strlen(strHelloWorld) << endl;
    return 0;
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZkNq67Tw-1591808470672)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

C++指针

c++中内存单元内容和地址

◆ 内存有很多内存单元构成。这些内存单元存放着各种类型的数据。

◆ 计算机对内存的每个内存单元都进行了编号,这个编号就称为内存地址,地址决定了内存单元在内存中的位置。

◆ 记住这些内容单元并不方便,于是c++语言的编译器让我们通过名字来访问这些内存地址。

指针的定义和间接访问操作

指针是一个变量,其值为另一个变量的地址,即,内存位置的直接地址。就像其他变量或常量一样,您必须在使用指针存储其他变量地址之前,对其进行声明。指针变量声明的一般形式为:

type *var-name;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z8yTont2-1591808470674)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

type 是指针的基类型,它必须是一个有效的 C++ 数据类型,var-name 是指针变量的名称。用来声明指针的星号 * 与乘法中使用的星号是相同的。但是,在这个语句中,星号是用来指定一个变量是指针。以下是有效的指针声明:

int    *ip;    /* 一个整型的指针 */
double *dp;    /* 一个 double 型的指针 */
float  *fp;    /* 一个浮点型的指针 */
char   *ch;    /* 一个字符型的指针 */

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UMWuCRxp-1591808470674)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

所有指针的值的实际数据类型,不管是整型、浮点型、字符型,还是其他的数据类型,都是一样的,都是一个代表内存地址的长的十六进制数。不同数据类型的指针之间唯一的不同是,指针所指向的变量或常量的数据类型不同。

C++ 中使用指针

使用指针时会频繁进行以下几个操作:定义一个指针变量、把变量地址赋值给指针、访问指针变量中可用地址的值。这些是通过使用一元运算符 ***** 来返回位于操作数所指定地址的变量的值。下面的实例涉及到了这些操作:

#include "stdafx.h"
#include 

using namespace std;

int main()
{
	int  var = 20;   // 实际变量的声明
	int  *ip;        // 指针变量的声明

	ip = &var;       // 在指针变量中存储 var 的地址

	cout << "Value of var variable: ";
	cout << var << endl;

	// 输出在指针变量中存储的地址
	cout << "Address stored in ip variable: ";
	cout << ip << endl;

	// 访问指针中地址的值
	cout << "Value of *ip variable: ";
	cout << *ip << endl;

	return 0;
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N874y1TF-1591808470675)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

重学C++ 重构C++知识体系_第1张图片[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q62pxR23-1591808470676)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

通过一个指针变量访问它所指向的地址的过程称为间接访问或解引指针访问.

#include "stdafx.h"
#include
using namespace std;

int main()
{
	int a = 112, b = -1;
	float c = 3.14f;
	int *d = &a;
	float* e = &c;
	cout << d << endl; cout << e << endl;
	cout << (*d) << endl; cout << (*e) << endl;
    return 0;
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0U7cwM5I-1591808470677)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

重学C++ 重构C++知识体系_第2张图片[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-acDBntcs-1591808470677)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

左值与右值

左值 (lvalue, locator value) 表示了一个占据内存中某个可识别的位置(也就是一个地址)的对象。

右值 (rvalue) 则使用排除法来定义。一个表达式不是 左值 就是 右值 。 那么,右值是一个 不 表示内存中某个可识别位置的对象的表达式。

几种c++中的原始指针

◆ const pointer 与pointer to const

判断准则为:以const为基准,在const左边最近的类型即为const所要修饰的类型,若左边无类型,则右边最近的类型为const所要修饰的类型。

char const* pStr1 我们发现const左边最近的类型为char,故const修饰的为char类型,即此指针所指向空间内的值是常量,不可修改。

char* const pStr2 我们发现const左边最近的类型为*,故const修饰的为指针本身,即指针所指向的空间不可修改。

char const* const pStr3 第一个const左边最近类型为char,第二个const左边最近类型为*,故指针所指向的空间与空间内的内容皆不可修改。

// pointer_demo3.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include

int main()
{
	char strHelloworld[] = { "helloworld" };
	char const* pStr1 = "helloworld";//pStr1指针所指向空间内的内容是常量,不可更改
	char* const pStr2 = strHelloworld;//pStr2指针所指向的空间不能更改
	char const* const pStr3 = "helloworld";//指针所指向空间和空间内的内容皆不可更改

	pStr1 = strHelloworld;       
	pStr2 = strHelloworld;  //pStr2不可更改
	pStr3 = strHelloworld;//pStr3不可更改
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oMxy1uDQ-1591808470678)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

◆ 关于const修饰的部分:

\1. 看左侧最近的部分

\2. 如果左侧没有看右侧

◆ 指向指针的指针

指向指针的指针是一种多级间接寻址的形式,或者说是一个指针链。通常,一个指针包含一个变量的地址。当我们定义一个指向指针的指针时,第一个指针包含了第二个指针的地址,第二个指针指向包含实际值的位置。

C++ 中指向指针的指针[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bNo3NgNy-1591808470678)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

一个指向指针的指针变量必须如下声明,即在变量名前放置两个星号。例如,下面声明了一个指向 int 类型指针的指针:

int **var;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wUwppmgL-1591808470679)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

当一个目标值被一个指针间接指向到另一个指针时,访问这个值需要使用两个星号运算符,如下面实例所示:

// pointer_demo4.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include 

using namespace std;

int main()
{
	int  var;
	int  *ptr;
	int  **pptr;

	var = 3000;

	// 获取 var 的地址
	ptr = &var;

	// 使用运算符 & 获取 ptr 的地址
	pptr = &ptr;

	// 使用 pptr 获取值
	cout << "var 值为 :" << var << endl;
	cout << "*ptr 值为:" << *ptr << endl;
	cout << "**pptr 值为:" << **pptr << endl;

	return 0;
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Z5bscPBo-1591808470679)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

重学C++ 重构C++知识体系_第3张图片[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sUnEs5ah-1591808470680)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

◆ *操作符具有从右向左的结合性

int a = 123;
int* b = &a;
int **c = &b;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hGZk7pJx-1591808470681)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

*这个表达式相当于(*c),必须从里往外逐层求值;

*c得到的是指向c的位置即b;

**c 相当于*b,得到变量a的值。

◆未初始化和非法的指针

◆ &与*操作符

取地址运算符 &

& 是一元运算符,返回操作数的内存地址。例如,如果 var 是一个整型变量,则 &var 是它的地址。该运算符与其他一元运算符具有相同的优先级,在运算时它是从右向左顺序进行的。

您可以把 & 运算符读作**“取地址运算符”,这意味着,&var** 读作"var 的地址"。

间接寻址运算符 *

第二个运算符是间接寻址运算符 ,它是 & 运算符的补充。 是一元运算符,返回操作数所指定地址的变量的值。

#include 
 
using namespace std;
 
int main ()
{
   int  var;
   int  *ptr;
   int  val;

   var = 3000;

   // 获取 var 的地址
   ptr = &var;

   // 获取 ptr 的值
   val = *ptr;
   cout << "Value of var :" << var << endl;
   cout << "Value of ptr :" << ptr << endl;
   cout << "Value of val :" << val << endl;

   return 0;
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GOnXCqiA-1591808470681)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

◆原始指针的基本运算

关于++++,----等运算符

栈和队列

栈先进后出,队列先进先出

stack 和heap

分配和回收动态内存的规则

资源管理方案RAII

C++中几种变量的对比

内存泄漏问题

c++的智能指针

C++中的引用

引用是什么?

引用变量是一个别名,也就是说,它是某个已存在变量的另一个名字。一旦把引用初始化为某个变量,就可以使用该引用名称或变量名称来指向变量。

C++ 引用 vs 指针

引用很容易与指针混淆,它们之间有三个主要的不同:

  • 不存在空引用。引用必须连接到一块合法的内存。
  • 一旦引用被初始化为一个对象,就不能被指向到另一个对象。指针可以在任何时候指向到另一个对象。
  • 引用必须在创建时被初始化。指针可以在任何时间被初始化。

C++ 中创建引用

int i = 17;
//我们可以为 i 声明引用变量,如下所示
int&  r = i;
double& s = d;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w25fDAiu-1591808470682)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

在这些声明中,& 读作引用。因此,第一个声明可以读作 “r 是一个初始化为 i 的整型引用”,第二个声明可以读作 “s 是一个初始化为 d 的 double 型引用”。下面的实例使用了 int 和 double 引用:

#include "stdafx.h"
#include 

using namespace std;

int main()
{
	// 声明简单的变量
	int    i;
	double d;

	// 声明引用变量
	int&    r = i;
	double& s = d;

	i = 5;
	cout << "Value of i : " << i << endl;
	cout << "Value of i reference : " << r << endl;

	d = 11.7;
	cout << "Value of d : " << d << endl;
	cout << "Value of d reference : " << s << endl;

	return 0;
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-V12CP8R5-1591808470682)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

C++的基本句法

三种基本的程序结构

顺序、分支和循环

自定义结构–枚举

**枚举类型的定义:**枚举类型(enumeration)是 C++ 中的一种派生数据类型,它是由用户定义的若干枚举常量的集合。

定义格式:枚举类型的定义格式为:

enum <类型名> {<枚举常量表>};

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7VUPMFnc-1591808470683)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

格式说明:

  • 关键字enum——指明其后的标识符是一个枚举类型的名字。
  • 枚举常量表——由枚举常量构成。“枚举常量"或称"枚举成员”,是以标识符形式表示的整型量,表示枚举类型的取值。枚举常量表列出枚举类型的所有取值,各枚举常量之间以","间隔,且必须各不相同。取值类型与条件表达式相同。

应用举例:

enum color_set1 {RED, BLUE, WHITE, BLACK}; // 定义枚举类型color_set1
enum week {Sun, Mon, Tue, Wed, Thu, Fri, Sat}; // 定义枚举类型week

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DESCpVdH-1591808470683)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

枚举常量代表该枚举类型的变量可能取的值,编译系统为每个枚举常量指定一个整数值,默认状态下,这个整数就是所列举元素的序号,序号从0开始。 可以在定义枚举类型时为部分或全部枚举常量指定整数值,在指定值之前的枚举常量仍按默认方式取值,而指定值之后的枚举常量按依次加1的原则取值。 各枚举常量的值可以重复。

实例

口袋中有红、黄、蓝、白、黑五种颜色的球若干个,每次从口袋中取三个不同颜色的球,统计并输出所有的取法。

**分析:**由于球只能是五种颜色之一,故可用枚举类型表示球的颜色。设取出的球为i、j、k,根据题意,i、j、k分别可以有五种取值,且i≠j≠k。可以用穷举法,逐个检验每一种可能的组合,从中找出符合要求的组合并输出。

#include
#include
using namespace std;
int main(){
    enum color_set {red,yellow,blue,white,black}; //声明枚举类型color
    color_set color; 
    int i,j,k,counter=0,loop; //counter是累计不同颜色的组合数
    for(i=red;i<=black;i++) {
        for(j=red;j<=black;j++) {
            if(i!=j){                        //前两个球颜色不同
                for(k=red;k<=black;k++)
                if(k!=i&&k!=j){        //第三个球不同于前两个,满足要求
                    counter++;
                    if((counter)%22==0){ //每屏显示22行
                        cout<<"请按回车键继续";
                        cin.get();
                    }
                    cout<<setw(15)<<counter;
                    /*下面输出每种取法,一行为一种取法的三个颜色*/
                    for(loop=1;loop<=3;loop++){
                        switch(loop){
                            case 1: color=(color_set) i; break;    //第一个是i
                            case 2: color=(color_set) j; break;    //第二个是j
                            case 3: color=(color_set) k; break;    //第三个是k
                        }
                        switch(color){
                            case red:   cout<<setw(15)<<"red";   break;
                            case yellow:cout<<setw(15)<<"yellow";break;
                            case blue:  cout<<setw(15)<<"blue";  break;
                            case white:    cout<<setw(15)<<"white"; break;
                            case black: cout<<setw(15)<<"black"; break;
                        }
                    }
                    cout<<endl;            //输出一种取法后换行
                }
            }
        }
    }
    cout<<"共有:"<<counter<<"种取法"<<endl;
    return 0;
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VfghJHUm-1591808470684)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

自定义结构–结构体和联合体

联合体是一种数据格式,可以保存不同的数据类型,但一次只能存在一种类型。联合体可以持有一个int或一个long或double。

#include 
#include 
 
using namespace std;
 
// 声明一个结构体类型 Books 
struct Books
{
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
};
 
int main( )
{
   Books Book1;        // 定义结构体类型 Books 的变量 Book1
   Books Book2;        // 定义结构体类型 Books 的变量 Book2
 
   // Book1 详述
   strcpy( Book1.title, "C++ 教程");
   strcpy( Book1.author, "Runoob"); 
   strcpy( Book1.subject, "编程语言");
   Book1.book_id = 12345;
 
   // Book2 详述
   strcpy( Book2.title, "CSS 教程");
   strcpy( Book2.author, "Runoob");
   strcpy( Book2.subject, "前端技术");
   Book2.book_id = 12346;
 
   // 输出 Book1 信息
   cout << "第一本书标题 : " << Book1.title <<endl;
   cout << "第一本书作者 : " << Book1.author <<endl;
   cout << "第一本书类目 : " << Book1.subject <<endl;
   cout << "第一本书 ID : " << Book1.book_id <<endl;
 
   // 输出 Book2 信息
   cout << "第二本书标题 : " << Book2.title <<endl;
   cout << "第二本书作者 : " << Book2.author <<endl;
   cout << "第二本书类目 : " << Book2.subject <<endl;
   cout << "第二本书 ID : " << Book2.book_id <<endl;
 
   return 0;
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-znG5Kb9u-1591808470684)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

结构体数据对齐–缺省对齐原则

函数

指向函数的指针与返回指针的函数

第7章 C++高级语法

深入剖析C++类型转换:显式转换的四种常见的方式,隐式转换类型转换的影响; 用通俗易懂的方式深入浅出讲解异常,IO,文件,线程,模版编程,这些很难难用的部分;

7-1 从抽象到面向对象编程

抽象是一种认识事物本质的方法

面向对象–类

♦ c++ 使用struct、class来定义一个类

  • struct的默认权限是public
  • class的默认权限是private
  • 除此以外,二者基本无差别

♦ 举例:

class Student{
private://成员变量
string name;
double score;

public://成员函数
double GetScore(){
return score;
}
};

♦ 对象是对现实世界中具体事物的反映, 继承是对物体分类的反映?
NO! 长方形和正方形 现实世界的东西,不能直接映射到软件编程中。
只是一个抽象的概念。

抽象–具体类型

♦ 让自定义的类像内置类型一样;
一个int类型的变量,可以完成+,-,*,/,比较,输出,++等一系列操作;

一个黑盒,一个抽象。

拷贝构造过程

Complex(const Complex& x); // 拷贝构造

//
// Created by caius on 2020/6/11.
//

#ifndef DEMO7_1_COMPLEX_H
#define DEMO7_1_COMPLEX_H


#pragma once

#include 
using namespace std;

class Complex
{
public:
    Complex();                                    // 默认构造函数
    Complex(double r,  double i);      // 构造函数
    virtual ~Complex();                      // 析构函数
    Complex(const Complex& x);      // 拷贝构造
    Complex& operator=(const Complex &c); // =号运算符


    double GetReal( ) const { return _real; }
    void SetReal(double d) { _real = d; }
    double GetImage() const { return _image; }
    void SetImage(double i) { _image = i; }

    // 运算符重载
    Complex operator+(const Complex &c) const;
    Complex& operator+=(const Complex &c);
    Complex operator-(const Complex &c) const;
    Complex& operator-=(const Complex &c);
    Complex operator*(const Complex &c) const;
    Complex& operator*=(const Complex &c);
    Complex operator/(const Complex &c) const;
    Complex& operator/=(const Complex &c);

    bool operator==(const Complex &c) const;
    bool operator!=(const Complex &c) const;
    bool operator>(const Complex &c)  const;
    bool operator>=(const Complex &c) const;
    bool operator<(const Complex &c) const;
    bool operator<=(const Complex &c) const;


    // 前置和后置++
    Complex& operator++();   //前置++
    Complex operator++(int); //后置++
    Complex& operator--();   //前置--
    Complex operator--(int); //后置--

//protected:

    friend ostream& operator<<(ostream& os, const Complex &x);
    friend istream& operator>>(istream& is, Complex &x);

private:
    double _real;             // 复数的实部
    double _image;         // 复数的虚部
};

#endif //DEMO7_1_COMPLEX_H
#include "Complex.h"

Complex::Complex()
{
    _real = 0.0;
    _image = 0.0;
    //cout << "Complex::Complex()" << endl;
}

Complex::Complex(double r, double i)
{
    _real = r;
    _image = i;
    //cout << "Complex::Complex(double r, double i)" << endl;
}

Complex::Complex(const Complex& c)
{
    _real = c._real;
    _image = c._image;
    //cout << "Complex::Complex(const Complex& c)" << endl;
}

Complex& Complex::operator= (const Complex& c)
{
    if (this != &c)
    {
        _real = c._real;
        _image = c._image;
    }
    return *this;
}

Complex::~Complex()
{
    _real = _image = 0.0;
    //cout << "Complex::~Complex()" << endl;
}

Complex Complex::operator+ (const Complex& c) const
{
    //Complex tmp;
    //tmp._real = _real + x._real;
    //tmp._image = _image + x._image;
    //return tmp;

    return Complex(_real + c._real, _image + c._image);
}


Complex& Complex::operator+= (const Complex& c)
{
    _real += c._real;
    _image += c._image;

    return *this;
}

Complex Complex::operator-(const Complex &c) const
{
    return Complex(_real - c._real, _image - c._image);
}

Complex& Complex::operator-=(const Complex &c)
{
    _real -= c._real;
    _image -= c._image;

    return *this;
}

Complex Complex::operator*(const Complex &c) const
{
    return Complex(_real*c._real - _image*c._image, _real*c._image + _image*c._real);
}

Complex& Complex::operator*=(const Complex &c)
{
    Complex tmp(*this);  //拷贝构造函数
    _real = tmp._real*c._real - _image*c._image;
    _image = tmp._real*c._image + tmp._image*c._real;
    return *this;
}

Complex Complex::operator/(const Complex &c) const
{
    double t = c._real*c._real + c._image*c._image;
    return Complex((_real*c._real - _image*(-c._image)) / t, (_real*(-c._image) + _image*c._real) / t);
}

Complex& Complex::operator/=(const Complex &c)
{
    Complex tmp(*this);  //拷贝构造函数
    double t = c._real*c._real + c._image*c._image;
    _real = (tmp._real*c._real - tmp._image*(-c._image)) / t;
    _image = (tmp._real*(-c._image) + tmp._image*c._real) / t;
    return *this;
}

bool Complex::operator==(const Complex& c) const
{
    return (_real == c._real) && (_image == c._image);
}

bool Complex::operator!=(const Complex& c) const
{
    return !( (_real == c._real) && (_image == c._image) );
}

bool Complex::operator>(const Complex &c)  const
{
    return (_real > c._real) && (_image > c._image);
}

bool Complex::operator>=(const Complex &c) const
{
    return (_real >= c._real) && (_image >= c._image);
}

bool Complex::operator<(const Complex &c) const
{
    return (_real < c._real) && (_image < c._image);
}

bool Complex::operator<=(const Complex &c) const
{
    return (_real <= c._real) && (_image <= c._image);
}


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

Complex Complex::operator++ (int) // 后置++
{
    //Complex tmp(*this);
    //_real++;
    //_image++;
    //return tmp;
    return Complex(_real++, _image++);  //先返回在增
}

Complex& Complex::operator--()   //前置--
{
    _real--;
    _image--;
    return *this;
}

Complex Complex::operator--(int) //后置--
{
    return Complex(_real--, _image--);
}

ostream& operator<<(ostream& os, const Complex &x)
{
    os << "real value is  " << x._real << "  image value is " << x._image;
    return os;
}

istream& operator >> (istream& is, Complex &x)
{
    is >> x._real >> x._image;
    return is;
}
#include 
#include "Complex.h"
//


int main()
{
    //Complex a(1.0, 2.0);
    //cout << a.GetReal() << endl;     // 1.0
    //cout << a.GetImage() << endl;  // 2.0
    //a.SetImage(2.0);
    //a.SetReal(3.0);
    //cout << a.GetReal() << endl;     // 3.0
    //cout << a.GetImage() << endl;  // 2.0

    //Complex a(3.0, 2.0);
    //Complex b(2.0, 3.0);
    //Complex c(a + b);
    //Complex d(c);

    //Complex e;
    //e = d++;
    //cout << e << endl;
    //cout << d << endl;
    //e = ++d;
    //cout << e << endl;
    //cout << d << endl;
    //cout << (e == d) << endl;  // 1
    //cout << (e == a) << endl;  // 0
    //cout << (e != d) << endl;   // 0
    //cout << (e != a) << endl;   // 1
    //
    //cin >> e;
    //cout << e << endl;
    //e += a;
    //cout << e << endl;

    // 测试各个运算符重载
    Complex a(2, 3);
    Complex b(3, 4);
    Complex c1 = a + b;
    cout << c1 << endl;
    Complex c2 = a - b;
    cout << c2 << endl;
    Complex c3 = a * b;
    cout << c3 << endl;
    Complex c4 = a / b;
    cout << c4 << endl;
    cout << endl;

    cout << (a == b) << endl;
    cout << (a != b) << endl;
    cout << (a > b) << endl;
    cout << (a >= b) << endl;
    cout << (a < b) << endl;
    cout << (a <= b) << endl;
    cout << endl;

    c1 = a;
    cout << c1 << endl;
    c2 = a++;
    cout << c2 << endl;
    cout << a << endl;
    c3 = ++a;
    cout << c3 << endl;
    cout << a << endl;
    cout << endl;

    c2 = b;
    cout << c2 << endl;
    c3 = b--;
    cout << c3 << endl;
    cout << b << endl;
    c3 = --b;
    cout << c3 << endl;
    cout << b << endl;

    return 0;
}

io 缓存流

7-2 面向对象的抽象法则1-具体类型的抽象

7-3 对象的属性

7-4 运算符重载

7-5 拷贝构造及临时对象的优化

7-6 前置与后置操作符

7-7 标准输入输出IO重载

7-8 IO流基础

7-9 IO缓存区

7-10 文件操作基础

7-11 文本文件的操作

7-12 二进制文件的操作

7-13 Complex其他运算符重载

7-14 头文件重复包含问题

7-15 关于前七章的练习题及答案

7-16 深拷贝浅拷贝及move语义的优化

7-17 面向对象的抽象法则2

7-18 Hack对象模型和虚函数

7-19 面向对象三大特性及总结

第8章 C++编程思想

深入再谈Class;深入再谈面向对象模式,23种设计模式的思路和最常用的单例,观察者模式等在工程中的实际使用;分析C++模版编程范式;

8-1 软件的设计模式

8-2 单例模式。

8-3 static和单例模式的实现

8-4 观察者模式

8-5 list的使用和观察者模式的实现1

8-6 观察者模式的实现2

8-7 void星NULL和nullptr

8-8 static_cast的使用

8-9 reinterpret_cast的使用

8-10 static_cast和dynamic_cast的使用

8-11 Adapter模式和多重继承

8-12 Adapter组合方式实现

8-13 设计模式总结

8-14 泛型编程之泛型函数1

8-15 泛型编程之泛型函数2

8-16 泛型编程的递推过程及总结

第9章 C++进阶编程

深入讲解STL思想,细致讲解容器,算法,C++内存分配,迭代器等STL编程方法,String类等,讲解Boost库的使用技巧;

9-1 STL标准库简介

9-2 序列型容器和函数对象基本使用

9-3 关联容器map的基本使用和查找

9-4 关联容器的插入删除及迭代器失效问题

9-5 从函数指针到仿函数模板

9-6 算法transform和lambda表达式

9-7 STL容器的统计与二分查找

9-8 从手写全排列到STL的实现

9-9 迭代器基本使用

9-10 手写GC与异常

9-11 自定义迭代器与手写GC

9-12 容器适配器

9-13 空间配置器初步

9-14 自定义空间配置器

9-15 STL空间配置器源码剖析与STL总结

9-16 关于Boost库

9-17 CPP多线程基础

9-18 多线程银行存取款案例

9-19 多线程小结

第10章 桌面应用项目实战:设计项目的架构和标准

项目的实现效果介绍及项目使用的技术框架;

10-1 慕影项目的效果展示

10-2 项目环境的安装和部署

10-3 项目的基本架构和pro文件

10-4 项目中用到的大致QT知识

第11章 实现项目《慕影》的通用组件模块:

介绍QT项目的基本类库,字符串类,智能指针类及调试信息等;

11-1 QT和VS的项目使用

11-2 QT项目的基础架构类和UI类

11-3 QQString的基本使用

11-4 QDebug的基本使用

11-5 QT的智能指针QScopedPointer

11-6 QThread的使用

第12章 《慕影》播放器UI模块开发

实现项目UI部分,qml与C++的交互方式,换肤模块的开发;

12-1 项目的整体UI架构

12-2 项目资源和UI加载的流程

12-3 qml的最基本使用和项目绑定

12-4 修正一个bug和框架调整

12-5 qml属性的基本使用

12-6 项目的换肤实现1

12-7 项目的换肤实现2

12-8 项目的换肤实现3

12-9 项目的换肤实现4

第13章 实现《慕影》音视频模块开发

实现项目PCM, 核心音频模块功能,核心视频模块功能,了解开源架构ffmpeg的设计和使用;

13-1 音视频采样编码的基本原理

13-2 ffmpeg的基本情况

13-3 PCM过程的一些基本参数

13-4 读取PCM音频文件进行播放1

13-5 读取PCM音频文件进行播放2

13-6 视频的封装格式及播放的基本流程

13-7 ffmpeg的解码大致流程

13-8 ffmpeg程序的环境配置

13-9 ffmpeg编写解码程序1

13-10 ffmpeg编写解码程序2

13-11 ffmpeg编写解码程序3

13-12 ffmpeg编写解码程序4

第14章 《慕影》播放器项目总结

项目整体的代码讲解,分析与总结

14-1 项目总结

14-2 项目UI功能总结

14-3 项目播放功能总结1

14-4 项目播放功能总结2

第15章 C++的陷阱和经验

通过剖析C++常见经典著作和对一些大牛的经验解读,排除大家学习C++的坑,为大家将来成为C++技术大牛铺设一条基本路线;

15-1 谈谈个人的学习工作经历试看

15-2 谈谈个人学习工作的一点感悟

15-3 推荐几本CPP的书籍

15-4 谈谈CPP的陷阱

第16章 课程总结

[参考][https://www.jianshu.com/p/0b60f21433c0]

你可能感兴趣的:(c++)