跳转到内容
BrushUP
返回 打印

面向对象编程(C++)一码知天下(合集版)

面向对象编程(C++)

第一章:从面向过程到面向对象的过渡案例

PSO作业参考demo(C++)

内容说明:粒子群优化算法(PSO)作业源码参考,包含PSO类定义、类实现、辅助函数和主函数。

PSO.h — 粒子群算法类定义

#ifndef _PSO_H_
#define _PSO_H_

const int DIMENSION=30;   //函数优化的维度(自变量个数)

/*--------------------------------------------------*
                   PSO类定义--粒子个体类
*---------------------------------------------------*/
class PSO
{
	//------------------PSO类数据成员---------------
private:
	//1.粒子个体信息
	double x[DIMENSION];//粒子位置向量
	double v[DIMENSION];//粒子速度向量
	double fitness;//粒子适应度数值

	//2.粒子局部最优信息
	double pbestx[DIMENSION];//粒子局部最优位置
	double pbestfitness; //粒子局部最优适应度数值

	//3.粒子群全局最优信息(共享信息)
	static double gbestx[DIMENSION];//全局最优位置
	static double gbestFintness;//全局最优适应度值

	//------------------PSO类函数成员---------------
public:
	PSO();//构造函数
	~PSO();//析构函数
	
	//普通函数(获取粒子个体的相关信息)
	double* getX();//获得粒子的位置向量
	double* getV();//获得粒子的速度向量
	double& getFitness();//获得粒子的适应度
	double* getPbestX();//获得粒子的局部最优位置向量
	double& getPbestFitness();//获得粒子的局部最优适应度数值

	//普通函数:初始化位置和速度向量
	void initi(double xmin, double xmax, double vmin, double vmax);

	//普通函数:计算粒子的适应度(待优化的函数的值)
	double computeFitness(double x[], int dim);

	//普通函数:更新子局部最优和全局最优信息
	void updatePbestX();//更新粒子个体局部最优位置
	void updateGbestX();//更新粒子群体的全局最优位置

	//普通函数:更新粒子的速度和位置向量-生成新的位置
	void updateV(int iter);
	void updateX(int iter);

	//-----------------------------------------------------

	//静态函数:获取全局最佳粒子信息
	static double* getGbestX();//获得全局最佳位置向量
	static double& getGbestFitness();//获得全局最佳适应度数值

	//静态函数:输出全局最佳粒子信息
	static void printGbestX();
	static void printGbestFitness();
};

#endif

PSO.cpp — 粒子群算法类实现


#include <iostream>
#include <cmath>
#include <cstdlib>
#include "PSO.h"
#include "function.h"

using namespace std;


//初始化类中的静态数据成员
double PSO::gbestx[DIMENSION] = {0.0};//全局最优位置初始化
double PSO::gbestFintness=pow(2,1024);//全局最优适应度值初始化,一个较大的值


//外部全局变量导入本文件,以供使用
extern int MAX_ITER;

extern double xmax;
extern double xmin;


extern double vmax;
extern double vmin;

//--------------------PSO类的函数定义------------------------------


PSO::PSO()
{
	//cout << "调用构造函数完成初始化" << endl;
}


PSO::~PSO()
{
	//cout << "调用析构函数完成对象释放" << endl;
}

double * PSO::getX()
{
	return x;//返回位置首地址
}

double * PSO::getV()
{
	return v;
}

double & PSO::getFitness()
{

	return fitness;
}

double * PSO::getPbestX()
{
	return pbestx;
}

double & PSO::getPbestFitness()
{
	return pbestfitness;
}

void PSO::initi(double xmin, double xmax, double vmin, double vmax)
{
	//初始化粒子个体的位置和速度
	for (int i = 0; i < DIMENSION; i++)
	{
		x[i] = xmin + (rand() / (32767 + 1.0)) *(xmax - xmin);
		v[i] = vmin + (rand() / (32767 + 1.0))*(vmax - vmin);
	}


	//计算当前粒子最初的适应度
	fitness = computeFitness(x,DIMENSION);


	//初始化粒子最初的局部最优位置和适应度
	for (int i = 0; i < DIMENSION; i++)
	{
		pbestx[i] = x[i];
	}

	pbestfitness = fitness;

}


//适应度:某个函数f的数值(计算结果越小说明对应的解越好)
double PSO::computeFitness(double x[], int dim)
{
	fitness = sphere(x, dim);//函数Sphere作为测试函数,其他函数自行测试
	//fitness = Rosenbrock(x, DIMENSION);//函数Rosenbrock作为测试函数
	//fitness = Ackley(x, DIMENSION);
	//fitness = Griewanks(x, DIMENSION);


	return fitness;
}

//更新局部最优位置
void PSO::updatePbestX()
{
	if (fitness<pbestfitness)
	{
		pbestfitness = fitness;

		for (int i = 0; i < DIMENSION; i++)
		{
			pbestx[i] = x[i];
		}	
	}
}


//更新全局最优位置
void PSO::updateGbestX()
{
	if (pbestfitness<=gbestFintness)
	{
		gbestFintness = pbestfitness;

		for (int i = 0; i < DIMENSION; i++)
		{
			gbestx[i] = pbestx[i];
		}
	}
	else;
}

void PSO::updateV(int iter)
{
	//更新公式参数
	double w = 0.9 - 0.5*iter / MAX_ITER;
	double c1 = 2.0;
	double c2 = 2.0;

	//注意r1,r2是随机生成的小数,需要将其放在for内,每次都产生新的随机数,随机性越高,求解精度越高
	for (int i = 0; i < DIMENSION; i++)
	{
		v[i] = w * v[i] + c1 *rand()/(32767 + 1.0)*(pbestx[i] - x[i]) + c2 * rand() / (32767 + 1.0)*(gbestx[i] - x[i]);
	
		//速度越界判断
		if (v[i]<=vmin || v[i]>=vmax)
		{
			v[i] = (vmax - vmin)*rand() / (32767 + 1.0);

		}
		else continue;
	}

}


void PSO::updateX(int iter)
{
	for (int i = 0; i < DIMENSION; i++)
	{
		x[i] = x[i] + v[i];

		//位置越界判断
		if (x[i] <= xmin || x[i] >= xmax)
		{
			x[i] = xmin+(xmax - xmin)*double(rand()/RAND_MAX);

		}
		else continue;
	}

}

//-----------------静态函数的定义--------------------

double * PSO::getGbestX()
{
	return gbestx;
}

double & PSO::getGbestFitness()
{
	return gbestFintness;
}

void PSO::printGbestX()
{
	cout <<endl<<"输出当前最好的解:" << endl<<endl;

	for (int dim = 0; dim < DIMENSION; dim++)
	{
		cout << "gbestX[" << dim << "] = " << gbestx[dim] << endl;

	}
	cout << endl;
}

void PSO::printGbestFitness()
{
	cout << "全局最优解的精度: " << gbestFintness << endl;
	cout << endl;
}

main.cpp — PSO主函数

/*************************************************
** 功能 : 粒子群优化算法演示
** 作者 : tsingke
** 时间 : 2019-11-22 / 10:54
***************************************************/

#include <iostream>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <windows.h>

#include "PSO.h"
#include "function.h"

using namespace std;

//算法迭代参数设置
int POPSIZE = 40;        //种群个体数目
int MAX_ITER = 7500;     //迭代次数


double accuracy = 1e-60; //搜索精度,误差精度,可以自己改


//搜索范围设置(位置范围,速度范围)
double xmax = 10;
double xmin = -10;

double vmax = 10;
double vmin = -10;

bool success = 0;
/*----------------------------------*
          Main Function
*-----------------------------------*/

int main()
{

	srand((unsigned)time(NULL));//产生伪随机数种子

	//1. 在堆上生成PSO类的对象数组,即粒子种群,共POPSIZE个个体
	PSO *swarm=new PSO[POPSIZE];


	//2. 初始化粒子群内所有粒子个体的信息(位置,速度,..等)
	for (int i = 0; i < POPSIZE; i++)
	{
		swarm[i].initi(xmin,xmax,vmin,vmax);
	}

	//3. 循环迭代-搜索目标函数的全局最优解

	cout << "---------------算法开始迭代-------------------" << endl;

	for (int iter = 0; iter < MAX_ITER; iter++)
	{
		for (int id = 0; id < POPSIZE; id++)
		{
			swarm[id].updatePbestX();//更新个体局部最优位置
			swarm[id].updateGbestX();//更新群体全局最优位置

	
			swarm[id].updateV(iter);//更新个体速度

			swarm[id].updateX(iter);//更新个体位置

			swarm[id].computeFitness(swarm[id].getX(),DIMENSION);//计算个体适应度

	
		}

		//判断是否达到要求
		if (PSO::getGbestFitness() <= accuracy)//达到设定的精度,中途输出结果,并停止后续迭代
		{
			cout << "搜索到符合精度的解(如下),算法停止搜索" << endl;

			PSO::printGbestX();       //输出全局最优解向量		
			PSO::printGbestFitness(); //输出全局最优解的精度
			success = 1;
			break;//跳出循环,停止迭代
		}


		cout << "迭代到第" << iter << "代, 本代最佳适应度数值(误差精度)= " << PSO::getGbestFitness()<<endl;

	}

	//4. 输出实验结果(未达到设定精度,依然输出结果)
	if (success==0)
	{

		PSO::printGbestX();//输出全局最优解向量	

		PSO::printGbestFitness();//输出搜索精度

	}

	//5. 释放申请的堆上的动态存储空间
	delete[] swarm;



	system("pause");
	
	return 0;
}

function.h — 测试函数声明

#ifndef FUNCTION_H
#define FUNCTION_H

double sphere(double x[], int dim);
double Rosenbrock(double x[], int dim);
double Ackley(double x[], int dim);
double Griewanks(double x[], int dim);

#endif

function.cpp — 测试函数实现

#include <cmath>
#include <cstdlib>
#include "function.h"

//Sphere函数
double sphere(double x[], int dim)
{
	double sum = 0;
	for (int i = 0; i < dim; i++)
	{
		sum += x[i] * x[i];
	}
	return sum;
}

//Rosenbrock函数
double Rosenbrock(double x[], int dim)
{
	double sum = 0;
	for (int i = 0; i < dim - 1; i++)
	{
		sum += 100 * (x[i+1] - x[i]*x[i])*(x[i+1] - x[i]*x[i]) + (x[i]-1)*(x[i]-1);
	}
	return sum;
}

//Ackley函数
double Ackley(double x[], int dim)
{
	double sum1 = 0, sum2 = 0;
	for (int i = 0; i < dim; i++)
	{
		sum1 += x[i] * x[i];
		sum2 += cos(2 * 3.1415926 * x[i]);
	}
	return -20 * exp(-0.2 * sqrt(sum1/dim)) - exp(sum2/dim) + 20 + 2.718281828;
}

//Griewanks函数
double Griewanks(double x[], int dim)
{
	double sum = 0, prod = 1;
	for (int i = 0; i < dim; i++)
	{
		sum += (x[i]*x[i])/4000;
		prod *= cos(x[i]/sqrt(i+1));
	}
	return sum - prod + 1;
}

Chapt_1_ReadData:C++文件读取演示

内容说明:演示如何使用C++的文件输入输出流从文件中读取数据、排序后再写入另一个文件。

c++读取文件.cpp

#include <iostream>
#include <fstream>
#include <cstdlib> //qsort在此头文件中声明
using namespace std;
const int MAX_NUM = 1000;
int a[MAX_NUM]; //存放文件中读入的整数
int MyCompare(const void * e1, const void * e2)
{ //用于qsort的比较函数
     return *((int *)e1) - *((int *)e2);
}
int main()
{
    int total = 0;//读入的整数个数
    ifstream srcFile("in.txt",ios::in); //以文本模式打开in.txt备读
    if(!srcFile) { //打开失败
        cout << "error opening source file." << endl;
        return 0;
    }
    ofstream destFile("out.txt",ios::out); //以文本模式打开out.txt备写
    if(!destFile) {
        srcFile.close(); //程序结束前不能忘记关闭以前打开过的文件
        cout << "error opening destination file." << endl;
        return 0;
    }
    int x;   
    while(srcFile >> x) //可以像用cin那样用ifstream对象
        a[total++] = x;
    qsort(a,total,sizeof(int),MyCompare); //排序
    for(int i = 0;i < total; ++i)
        destFile << a[i] << " "; //可以像用cout那样用ofstream对象
    destFile.close();
    srcFile.close();
    return 0;
}

chapt_1_ScoreSystem:学生成绩管理系统(C语言风格,面向过程)

内容说明:本章是第一章上机实验框架参考,用C语言风格的面向过程代码实现学生成绩管理系统,为后续转向OOP做铺垫。

main.c — 学生成绩管理系统主函数

#define  _CRT_SECURE_NO_WARNINGS

/*************************************************
** 功能 : 学生成绩管理系统
** 作者 : Qingke Zhang/tsingke@sdnu.edu.cn
** 版本 : v1.0
** 版权 : GNU General Public License(GNU GPL)
/**************************************************/


#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include "score.h"

/*----------------------------------*
		Main Function
*-----------------------------------*/

int main()
{

	printf("******************************\n");
	printf("       学生成绩管理分析系统        \n");
	printf("         Qingke Zhang            \n");
	printf("******************************\n\n");

	/*-1.变量初始化-*/
	int N = 0;            //学生总数
	SS  *pstu = NULL;    //学生数组-结构体数组指针实现

	//2.读取学生信息
	pstu = readDataFromFile(&N);

	/*-3.计算学生总成绩(总成绩 = 0.2*平时成绩 + 0.8*期末成绩)--*/
	calcuScore(pstu, N);

	/*-4.根据学生成绩排名-*/
	sortScore(pstu, N);

	/*-5.按照排名输出学生信息-*/
	printOut(pstu, N);

	/*-6.释放动态内存空间-*/
	free(pstu);


	system("pause");
	return 0;
}

score.h — 学生管理头文件


/*************************************************
* Head File   : SCORE.h
* File Usage  : 学生管理系统头文件
* Create Time : v1.0
/**************************************************/

#ifndef __SCORE_H__
#define __SCORE_H__


#include <stdio.h>

/*----------------------------------*
	   学生信息-结构体设计
*-----------------------------------*/

typedef struct student
{
	char number[10];  //学号
	char name[10];    //姓名
	float dailyScore;   //平时成绩
	float finalScore;   //期末成绩
	float generalScore; //总评成绩

}SS;


/*---------------函数声明-------------------*/

//1.读取学生基本数据
void readData(SS stu[], int N);
SS* readDataFromFile(int *N);

//2.计算N个学生各自总成绩
void calcuScore(SS stu[], int N);


//3.根据总评成绩排名
void sortScore(SS stu[], int N);


//4.按照一定的格式输出N个学生的完整信息
void printOut(SS stu[], int N);

#endif

score.c — 学生管理函数实现

/*************************************************
** 源文件   : score.c
** 功能说明 : Function Definitions
** 创建版本 : v1.0
/**************************************************/

/*----------------头文件--------------*/
#define  _CRT_SECURE_NO_WARNINGS
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include "SCORE.h"

/*----------------函数定义-------------*/

//1.1手动输入学生基本数据
void readData(SS stu[], int N)
{

	printf("请按照如下格式输入学生信息:学号,姓名,平时成绩,期末成绩\n");

	for (int i = 0; i < N; i++)
	{
		printf("%d个学生:", i + 1);
		scanf("%s %s %f %f", &stu[i].number, &stu[i].name, &stu[i].dailyScore, &stu[i].finalScore);
		printf("\n");
	}

	printf("------成绩录入完毕!--------\n");

}

//1.2从文件里读取学生基本数据
SS* readDataFromFile(int *N)
{

	printf("\n\n------第一步: 从文件读取学生的成绩信息--------\n\n");

	SS *stu;// 开辟新空间,存取文件中的每个学生信息

	FILE *fp = NULL;
	int count = 0;
	int index = 0;

	fp = fopen("data.txt", "r");

	//1.获取学生数目
	if (fp != NULL)
	{
		fscanf(fp, "%d", &count);
		*N = count;
	}
	else
	{
		printf("failed to open the info file\n");
		getchar();
	}

	printf("学生数目为:%d\n", count);


	//2.给所有学生分配存储空间
	stu = (SS*)malloc(count * sizeof(SS));


	//3.读取每条学生的信息
	while ((!feof(fp)))
	{

		//读入文件数据到内存	
		fscanf(fp, "%s%s%f%f\n", (stu[index].number), (stu[index].name), &stu[index].dailyScore, &stu[index].finalScore);

		//输出排序后的学生信息
		printf("* 学号:%s	姓名:%s		平时成绩:%4.2f分		期末成绩:%4.2f\n", (stu[index].number), (stu[index].name), stu[index].dailyScore, stu[index].finalScore);

		index++;
	}

	getchar();

	fclose(fp);

	return stu;
}

//2.计算N个学生各自的总评成绩
void calcuScore(SS stu[], int N)
{


	printf("\n\n------第二步: 计算每个学生的总评成绩--------\n\n");

	for (int i = 0; i < N; i++)
	{

		stu[i].generalScore = 0.2*stu[i].dailyScore + 0.8*stu[i].finalScore;
		printf("* 学号:%s	姓名:%s		总成绩:%4.2f\n", (stu[i].number), (stu[i].name), stu[i].generalScore);

	}

	getchar();
}


//3.根据总评成绩排名
int cmpBigtoSmall(const void *a, const void *b)
{

	SS *aa = (SS *)(a);
	SS *bb = (SS *)(b);



	if ((*aa).generalScore < (*bb).generalScore)  return 1;

	else if ((*aa).generalScore > (*bb).generalScore)  return -1;

	else
		return 0;

}

void sortScore(SS stu[], int N)
{

	qsort(&(stu[0]), N, sizeof(stu[0]), cmpBigtoSmall);

}

//4.按照一定的格式输出N个学生的信息
void printOut(SS stu[], int N)
{

	printf("\n------第三步: 根据总成绩输出学生排名信息!------\n\n");

	for (int i = 0; i < N; i++)
	{

		printf("%d名信息 学号:%s	姓名:%s		总成绩:%4.2f\n", i + 1, &(stu[i].number[0]), &(stu[i].name[0]), stu[i].generalScore);
	}

	getchar();

}

data.txt — 测试数据

6
201720398 zhang 84.7 96
201720224 wang 78 86
201711034 zhao 80 86
201711045 liu 69 75
201724397 TomHanks 85 90
201700925 Jeny 90 96

第二章:C++与C(C++新增语法特性)

内容说明:本章展示C++相对C新增的语法特性,包括内联函数、命名空间、new/malloc、引用、异常处理、const、默认参数等。

inlineFunction.cpp — 内联函数

/*************************************************
** 功能 : 内联函数的使用  
** 作者 : tsingke
** 时间 : 2019-9-24 / 00:42
***************************************************/

#include <iostream>
#include <cstdlib>
#include <windows.h>
#include <ctime>
#include <cmath>

using namespace std;

const int run = 100000000;



 int multiply_1(int x, int y)
{


	 return x*y;


}


 inline int multiply_2(int x, int y)
{


	 return x*y;



}
/*----------------------------------*
          Main Function
*-----------------------------------*/

int main()
{

	int t=0;


	int a = 1;
	int b = 2;


	/*----------------------------------*
	            普通函数调用时间统计
	*-----------------------------------*/
	int ss_1, ss_2;

	clock_t start_1, end_1;

	start_1 = clock();

	while (t<run)
	{
		 ss_1 = multiply_1(a++, b++);

		//cout << a << "^2 + " << b << "^2 = " << ss << endl;
		 t++;

	}
	end_1 = clock();


	cout << "普通函数执行总时间: " <<1.0*(end_1 - start_1)  << endl;


	/*----------------------------------*
			内联函数调用时间统计
    *-----------------------------------*/
	clock_t start_2, end_2;

	start_2 = clock();

	t = 0;
	while (t < run)
	{
		ss_2 = multiply_2(a++, b++);
		//cout << a << "^2 + " << b << "^2 = " << ss << endl;
		t++;

	}
	end_2 = clock();


	cout << "内联函数执行总时间: " << 1.0*(end_2 - start_2) << endl;





	system("pause");
	
	return 0;
}

namespace.cpp — 命名空间

/*************************************************
** 功能 : namespace  
** 作者 : tsingke
** 时间 : 2019-9-23 / 21:33
***************************************************/

#include <iostream>
#include <cstdlib>
#include <windows.h>
#include <string>

using namespace std;

namespace one
{

	int id;
	double salary;
}


namespace two
{

	int id;
	double salary;
}

namespace three
{

	int id;
	double salary;
	string address;
}
/*----------------------------------*
          Main Function
*-----------------------------------*/

using namespace one;

int main()
{


	/*-全部导入法-*/
	id = 2018;

	salary = 100000;


	/*-随用随取法-*/

	two::id = 2019;
	two::salary = 50000;
	
    

	/*-部分导入法-*/

	using three::id;

	id = 100;

	cout << "one::id = "<< one::id << endl;

	id = 999999;
	cout << "two::id = " <<id<< endl;

	cout << "one::id = "<< one::id << endl;

	//address = "sdnu";
	three::address = "sdnu";


	cout << three::address << endl;



	system("pause");
	
	return 0;
}

new-malloc.cpp — new与malloc对比

/*************************************************
** 功能 : new和malloc的使用演示 
** 作者 : tsingke
** 时间 : 2019-10-7 / 12:34
***************************************************/

#include <iostream>
#include <cstdlib>
#include <cstring>
#include <windows.h>

using namespace std;


/*----------------------------------*
          Main Function
*-----------------------------------*/

int main()
{

	/*----------------------------------*
	            使用malloc 和 free
	*-----------------------------------*/

	int *p1;

	p1= (int*)malloc(sizeof(int) * 10);

	

	memset(p1, 0, 10*sizeof(int));//初始化为0

	for (int i = 0; i < 10; i++)
	{
		cout << p1[i] << " ";
	}

	cout << endl;



	//初始化
	for (int  i = 0; i < 10; i++)
	{
		p1[i] = i;
		
		cout << (p1[i]) << " ";
	}

	cout << endl;


	/*-输出各个元素的物理存储地址-*/

	for (int i = 0; i < 10; i++)
	{
		cout << "地址: " << &p1[i] << endl;

	}

	cout << endl;

	free(p1);



	int *p3 = (int*)calloc(10, sizeof(int));

	for (int i = 0; i < 10; i++)
	{
		cout << p3[i] << " ";
	}

	cout << endl;


	/*----------------------------------*
	            使用new 和 delete
	*-----------------------------------*/


	int *p2;
	p2 = new int[10];

	for (int i = 0; i < 10; i++)
	{
		p2[i] = i*i;

		cout << p2[i] <<" ";
	}

	cout << endl;

	/*-输出各个元素的物理存储地址-*/

	for (int i = 0; i < 10; i++)
	{
		cout << "地址: " << &p2[i] << endl;

	}

	delete[] p2;



	/*----多维数组的申请-----*/

	int(*pt)[5] = new int[4][5];//pt[4][5]

	//初始化的方法
	for (int i = 0; i < 4; i++)
	{
		for (int j = 0; j < 5; j++)
		{
			pt[i][j] = i * j;

			cout << pt[i][j]<<" ";
		}

		cout << endl;
	}



	int(*ptt)[4][6] = new int[3][4][6];//ptt[3][4][6]

	delete[] pt;

	delete[] ptt; 




	system("pause");
	
	return 0;
}

referenceDemo1.cpp — 引用基础

/*************************************************
** 功能 : 引用的用法  
** 作者 : tsingke
** 时间 : 2019-10-8 / 14:50
***************************************************/

#include <iostream>
#include <cstdlib>
#include <windows.h>

using namespace std;


void swap(int &x, int &y)
{
	int temp;
	temp = x;
	x = y;
	y = temp;

}


int& func(int &x, int &y)
{


	int x = x + y;


	return x;

}

/*----------------------------------*
          Main Function
*-----------------------------------*/

int main()
{


	int a = 88;

	int b = 66;

	int &r = a;

	int &rrrrr = a;




	//r = 99;

	cout << "a= " <<a<< endl;
	cout << "r= " <<r<< endl;

	cout << "a的地址=" << &a << endl;
	cout << "r的地址=" << &r << endl;
	cout << "rrrr的地址=" << &rrrrr << endl;


	

	cout << "a= " << a << endl;
	cout << "b= " << b << endl;


	int c = a+b;
	swap(c, b);


	cout << "a= " << a << endl;
	cout << "b= " << b << endl;




	func(a, b);

	int xx= func(a, b) + 18;

	func(a, b) = 4;//x=4;







	system("pause");
	
	return 0;
}

referenceDemo2.cpp — 引用深入

/*************************************************
** 功能 : 引用的使用演示案例demo 
** 作者 : tsingke
** 时间 : 2019-10-8 / 10:08
***************************************************/

#include <iostream>
#include <cstdlib>
#include <windows.h>

using namespace std;


double sum(int x, int &y)
{

	x++;
	y++;

	return x + y;
}


int& sumref(int x,int &y)
{

	y = x + y;



	return y;
	//注意:不要返回局部变量的引用,因为局部变量离开所在函数就被系统释放回收了,即使起别名也没有任何使用价值.
	// 可以返回某个类型为引用的形参,例如这里的y就是一个引用形参类型,可以返回.


}


int func(int *p, int &r,int o)
{

	*p = 666;//通过指针改变指向的数值
	 r = 888;//通过引用改变指向的数值
	 o = 999;


	 cout << "指针*p的数值= " << *p << endl;
	 cout << "引用r的数值= " << r << endl;
	 cout << "整型o的数值= " << o << endl;

	return 0;
}

/*----------------------------------*
          Main Function
*-----------------------------------*/

int main()
{

	//1. 什么是引用:变量的别名

	int a1 = 100;
	int a2 = 200;

	int &r = a1;//声明时就要给引用初始化
	     r = a2;


	cout << "a的地址:" << &a1 << endl;
	cout << "r的地址:" << &r << endl;


	//2.哪些量不可以是引用

	//void va;    //不可以建立void变量的引用
	//int &&r = a;//不可以建立引用的引用
	//int & *p = a;//不允许使用指向指针的引用
	//int & arry[10] = a;//不允许使用引用的数组



	//3. 引用的作用1: 做函数的形参,做函数的返回类型

	sum(a1, a2);

	cout << "a1的数值= " << a1 << endl;
	cout << "a2的数值= " << a2 << endl;


   //4. 引用的作用2:作为函数的返回类型(例如:cin>>x执行完后返回的是cin对象的引用,还是cin)




	sumref(a1, a2);//独立的函数调用语句

	int s = sumref(a1, a2) + 8;//引用作为操作数

	sumref(a1, a2) = 3000;//引用作为左边的数值


	
	//5. 引用和指针的区别

	//引用:变量的别名, 本身直接操作指向的数据
	//指针:带有类型的地址,远程间接操作指向的数据
	
	int m = 1;
	int n = 2;
	int o = 3;

	func(&m, n,o);

	cout << "m = " << m << "  n= " << n << endl;


	system("pause");
	
	return 0;
}

try-catch_1.cpp — try-catch原理剖析

/*************************************************
** 功能 : try-catch 原理剖析  
** 作者 : tsingke
** 时间 : 2019-10-7 / 20:17
***************************************************/

#include <iostream>
#include <cstdlib>
#include <windows.h>

using namespace std;



void func1(int a);
void func2(int a);
void func3(int a);
void func4(int a);


//函数调用关系: fun1-->func2-->func3-->func4
/*----------------------------------*
          Main Function
*-----------------------------------*/

int main()
{	

	int x;

	cout << "请输入整数x= ";
	cin >> x;

	try
	{
		func1(x);

	}
	catch (const int e)
	{
		cout << "主函数内处理异常" << endl;
	}


	system("pause");
	
	return 0;
}

//-------------------子函数定义--------------------

void func1(int a)
{

	if (a == 1)
	{
		throw 1;
	}


	try
	{
		func2(a);

	}
	catch (int e)
	{
		cout << "func1 内处理异常" << endl;

	}


	cout << " i am func1" << endl;


}


void func2(int a)
{
	if (a == 2)
	{
		throw 2;
	}

	try
	{
		func3(a);

	}
	catch (int e)
	{
		cout << "func2 内处理异常" << endl;

	}
	cout << " i am func2" << endl;


}

void func3(int a)
{
	if (a == 3)
	{
		throw 3;
	}
	try
	{
		func4(a);

	}
	catch (int e)  
	{
		cout << "func3 内处理异常" << endl;

	}
	cout << " i am func3" << endl;


}

void func4(int a)
{
	if (a == 4)
	{
		throw 4;//如果引发异常,下面的输出语句将不会执行
	}

	cout << " i am func4" << endl;

}

try-catch_2.cpp — try-catch课堂演示

/*************************************************
** 功能 : try-catch课堂演示  
** 作者 : tsingke
** 时间 : 2019-10-7 / 12:51
***************************************************/

#include <iostream>
#include <cstdlib>
#include <windows.h>

using namespace std;



double add(int a, int b)
{

	if (a+b == 0)
	{
		throw -1;
		cout << "-1"<< endl ;
		
		
	}
	return double(a + b);

}

double subtraction(int a, int b)
{
	if (a - b == 0)
	{
		throw - 2;
		cout << "-2" << endl;

	}

	return double(a - b);
}

double multiplication(int a, int b)
{
	if (a * b == 0)
	{
		throw - 3;
		cout << "-3" << endl;

	}

	return double(a * b);
}

double divide(int a, int b)
{

	if (b == 0)
	{
		throw - 4;

		cout << "-4"<< endl ;
		
	}

	return double(1.0*a / b);
}


double rootsum(int a,int b)
{

	if (a<0 && b<0)
	{
		throw -1.2;

		cout << "-5" << endl;

	}

	return double(sqrt(a)+sqrt(b));
}
/*----------------------------------*
          Main Function
*-----------------------------------*/



int main()
{

	cout << "try- catch 使用演示" << endl ;
	int a, b;

	do 
	{
		try
		{
			cout << endl<< "------输入两个数,输出他们的四则运算结果-----" << endl;

			cout << "a = "; cin >> a;

			cout << "b = "; cin >> b;


			cout << "a+b = " << add(a, b) << endl;


			cout << "a-b = " << subtraction(a, b) << endl;
			cout << "a*b = " << multiplication(a, b) << endl;
			cout << "a/b = " << divide(a, b) << endl;

			cout << "sqrt(a)+sqrt(b)= " << rootsum(a, b) << endl;


		}
		catch (const int e)
		{
			switch (e)
			{
			case -1: cout << "异常发生: a+b == 0"; break;
			case -2: cout << "异常发生: a-b == 0"; break;

			case -3: cout << "异常发生: a*b == 0"; break;

			case -4: cout << "异常发生: a/b == null"; break;

			default:
				break;
			}

		}
		catch (const double f)
		{
			cout << f << endl;
			cout << "异常发生: a<0 或b <0 " << endl;
		}

		
	} while (1);


	
	system("pause");
	
	return 0;
}

constDemo.cpp — const基础

/*************************************************
** 功能 : const demo
** 作者 : tsingke
** 时间 : 2019-9-24 / 08:33
***************************************************/

#include <iostream>
#include <cstdlib>
#include <windows.h>

using namespace std;


int sum(const int *p1, const int *p2)
{
	//*p1 = 222;


	return (*p1 + *p2);

}


/*----------------------------------*
          Main Function
*-----------------------------------*/

int main()
{

	


	int a = 666;
	int b = 888;

	int c=sum(&a, &b);


	cout << "c= " << c << endl ;





	system("pause");
	
	return 0;
}

const与指针.cpp — const与指针

#include <iostream>
using namespace std;

int main()
{
    int i=100;
    int j=200;

    //1.指向常量的指针:指向的量是常量,故*p1不可变,但p1可变
#if 1

    const int *p1;

    *p1 = j;//错误
    p1=&j;  //正确


#endif

    //2.常指针:指针自己是常量, 故p2不可变, 但*p2可变
#if 1

    int* const p2=&i;

     p2 = &j; //错误
    *p2=j;    //正确


#endif

    //3.指向常量的常指针: 指针是常量,指针指向的也是常量,故都不能修改。
#if 1

    int const * const p3 =&i;

    p3=&j;//错误
    *p3=j;//错误

#endif
    return 0;
}

defaultArgument_1.cpp — 默认形参(基础)

/*************************************************
** 功能 :默认形参函数演示  
** 作者 : tsingke
** 时间 : 2019-10-8 / 14:29
***************************************************/

#include <iostream>
#include <cstdlib>
#include <windows.h>

using namespace std;



void func(int a, int b,int c)
{

	cout << a << endl;
	cout << b << endl;
	cout << c << endl;

}

void func_1(int a, int b=600, int c=800)
{

	cout << a << endl;
	cout << b << endl;
	cout << c << endl;

}






/*----------------------------------*
          Main Function
*-----------------------------------*/

int main()
{

	


	int a = 1;


	int b = 2;
	int c = 3;

	int a_1 = 3;


	//func(a, b, c);

	func_1(a);
	func_1(a, b);
	func_1(a, b, c);





	system("pause");
	
	return 0;
}

defaultArgument_2.cpp — 默认形参(深入)

/*************************************************
** 功能 : 函数默认形参演示  
** 作者 : tsingke
** 时间 : 2019-9-23 / 23:29
***************************************************/

#include <iostream>
#include <cstdlib>
#include <windows.h>

using namespace std;

void plot(int x , int y , int z = 0, char color = 'B');


//void plot(int x, int y, int z, char color)
//{
//
//	cout << "坐标x= " << x << endl;
//	cout << "坐标y= " << y << endl;
//	cout << "坐标z= " << z << endl;
//
//	cout << "颜色 c= "  <<color << endl ;
//
//}



//void plot(int x=0, int y=1, int z=0, char color='B')
//{
//
//	cout << "------图形的基本信息如下所示-------" << endl ;
//	cout << "坐标x= " << x << endl;
//	cout << "坐标y= " << y << endl;
//	cout << "坐标z= " << z << endl;
//
//	cout << "颜色 c= " << color << endl;
//
//}




/*----------------------------------*
          Main Function
*-----------------------------------*/

int main()
{
	

	int a = 3, b = 4, c = 5;
	char color = 'R';

	plot(a, b, c, color);//一一对应的方式

	plot(a, b);//
	




	system("pause");
	
	return 0;
}



//定义带默认形参的函数时,不要带上默认值,只在声明时带上!!!!
void plot(int x, int y, int z, char color)
{

	cout << x << y << z << color<< endl;


}

第三章:类与对象(上)

内容说明:本章进入面向对象编程核心——类与对象,包含this指针、构造函数、类对象使用、友元函数、浅拷贝与深拷贝。

this.cpp / constructor.cpp — 构造函数课堂演示

/*************************************************
** 功能 : 构造函数课堂演示
** 作者 : tsingke
** 时间 : 2019-10-21 / 18:18
***************************************************/

#include <iostream>
#include <cstdlib>

using namespace std;

class date
{
public:

    void inition(int y,int m, int d);
    date(); //无参构造函数

    date(int y, int m=1, int d=1);//有参构造函数(可以给定默认值)

    date(const date &r);//拷贝构造函数

    void display();

    ~date();

private:
    int year;
    int month;
    int day;
};

void date::inition(int y, int m, int d)
{
    this->year =y;
    this->month =m;
    this->day=d;
}

date::date()
{
    cout << "无参构造函数被调用" << endl;

}

date::date(int y,int m, int d)
{
    year = y;
    month = m;
    day = d;

    cout << "有参构造函数被调用" << endl;
}

date::date(const date & r)
{
    this->year = r.year;
    this->month = r.month;
    this->day = r.day;

    cout << "拷贝构造函数被调用" << endl;

}

void date::display()
{
   cout<<year<<"-"<<month<<"-"<<day<<endl;

   //cout<<"指针this指向地址:"<<this<<endl;

}


date::~date()
{
    cout << "*析构函数调用:" <<this<<endl;


}



/*----------------------------------*
          Main Function
*-----------------------------------*/

int main()
{

    date a;//对象a
    cout<<"对象a的地址:"<<&a<<endl;

    a.display();

    date b(2019);//对象b
    b.display();


    date c(b);//对象c
    c.display();



    return 0;

}

构造函数的使用(课堂范例).cpp

/*************************************************
** 功能 : 构造函数的使用  
** 作者 : tsingke
** 创建 : 2020-11-2 
** 版权 : tsingke@sdnu.edu.cn
**************************************************/

#include <iostream>
#include <cstdlib>
#include <windows.h>

using namespace std;

class Date
{

private: 
	int year, month, day;

public:
	Date()
	{
		cout << "无参构造函数被调用!" << endl;
	}

	Date(int year, int month, int day)
	{

		this->year = year;
		this->month = month;
		(*this).day = day;
		cout << "普通构造函数被调用!" << endl;
	}

	Date(const Date& r)
	{
		this->year = r.year;
		this->month = r.month;
		this->day = r.day;
		cout << "拷贝构造函数被调用!" << endl;
	}

	~Date()
	{
		cout << "~析构函数被调用(回车继续)!" << endl;
		getchar();
	}


};


//全局函数,返回类的对象类型
Date func(Date val)
{

	cout << "func()is called" << endl;

	return val;//调用拷贝构函,情形三
}


/*----------------------------------*
*         Main Function
*-----------------------------------*/

int main()
{

	Date lastday;//调用无参构函

	Date today(2020, 11, 1);//调用有参构函

	Date tommory(today);//调用拷贝构函(情形一)

	func(tommory);//调用拷贝构函(情形二)
	
	today = Date(2021,11,11);//调用普通有参构函,不会调用拷贝构函


	system("pause");
	
	return 0;
}

triangleDemo.cpp — 三角形类的演示

/*************************************************
** 功能 : 类的演示
** 作者 : tsingke
** 时间 : 2019-10-15 / 15:12
***************************************************/

#include <iostream>
#include <cstdlib>
#include <cmath>
#include <windows.h>

using namespace std;





class triangle
{

private:
	double a;
	double b;
	double c;

public:


	void inti(int, int, int);

	bool isTriangle();

	double perimeter();

	double area();

	int typeTriangle();

	void ModifyA(int);


};

bool triangle::isTriangle()
{

	if ((a + b) > c && (a + c) > b && (b + c) > a)
	{
		return true;
	}

	else
		return false;
}

void triangle::inti(int s1, int s2, int s3)
{

	a = s1;
	b = s2;
	c = s3;

	if (isTriangle() == false)
	{
		cout << "无法构成三角形,退出程序!" << endl;

		exit(0);
	}

}

double triangle::perimeter()
{

	return a + b + c;

}


double triangle::area()
{

	double  p = perimeter() / 2.0;

	return sqrt(p*(p - a)*(p - b)*(p - c));

}

int triangle::typeTriangle()
{

	if (pow(a, 2) + pow(b, 2) == pow(c, 2))
	{
		return 1;
	}
	else if (pow(a, 2) + pow(b, 2) < pow(c, 2))
	{
		return 2;
	}
	else
	{
		return 3;
	}




}

void triangle::ModifyA(int s)
{
	a = s;//间接修改边长a的数值
}


/*----------------------------------*
		  Main Function
*-----------------------------------*/

int main()
{
	triangle t;

	int ta, tb, tc;


	//t.a = 666;//无法直接访问私有数据

	t.ModifyA(6666);

	cout << "pleaes input three edges: " << endl;

	cin >> ta;
	cin >> tb;
	cin >> tc;

	t.inti(ta, tb, tc);


	cout << "周长=" << t.perimeter() << endl;
	cout << "面积= " << t.area() << endl;

	if (t.typeTriangle() == 1)
	{
		cout << "直角三角形" << endl;

	}
	else if (t.typeTriangle() == 2)
	{
		cout << "锐角三角形" << endl;

	}
	else
		cout << "钝角三角形" << endl;



	system("pause");

	return 0;
}

类对象的使用-一码知天下.cpp

/*************************************************
** 功能 : 对象的使用
** 作者 : tsingke
** 时间 : 2019-11-4 / 18:02
***************************************************/

#include <iostream>
#include <cstdlib>
#include <windows.h>

using namespace std;


class date
{
	//1.类的变量记心间
private:
	int year;
	int month;
	int day;

public:

	//2. 三构一析放在前
	date();
	date(int year, int month, int day);
	date(const date &r);
	~date();


	//3.普函定义按需添

	int getYear();
	int getMonth();
	int getDay();

	void setYear(int y);
	void setMonth(int m);
	void setDay(int d);



	void display();


};

//---------------类成员函数的实现----------------------
date::date()
{
	cout << "++无参构造函数被调用++" << endl;
	year = 2019;
	month = 01;
	day = 01;
}

date::date(int year, int month, int day)
{
	cout << "++有参构造函数被调用++" << endl;

	this->year = year;
	this->month = month;
	this->day = day;
}

date::date(const date & r)
{
	this->year = r.year;
	this->month = r.month;
	this->day = r.day;
}

date::~date()
{
	cout << "--析构函数被调用--" << endl;
}

int date::getYear()
{
	return year;
}

int date::getMonth()
{
	return month;
}

int date::getDay()
{
	return day;
}

void date::setYear(int y)
{
	this->year = y;
}

void date::setMonth(int m)
{
	this->month = m;
}

void date::setDay(int d)
{
	this->day = d;

}

void date::display()
{
	cout << year << "" << month << "" << day << "" << endl;
}


//==================全局函数=========================


void print(date &r)
{
	cout << r.getYear() << "" << r.getMonth() << "" << r.getDay() << "" << endl;
}


//对象作为参数(对象,对象指针,对象引用)
void objectAsArgument(date t, date * p, date & r)
{
	//传值形式无法修改原对象内容,但可以访问到原对象内相同的数据
	t.setYear(2050);
	t.setMonth(10);
	t.setDay(24);


	//通过指针修改原对象内容
	p->setYear(2035);
	p->setMonth(6);
	p->setDay(1);


	//通过引用修改原对象内容
	r.setYear(2050);
	r.setMonth(10);
	r.setDay(24);

}

/*----------------------------------*
		  Main Function
*-----------------------------------*/


//使用方法: 把#if 后面的0改成1即可调试对应区域代码

int main()
{


	
#if 0
	//----------------------第一块演示: 对象的数组----------------------------------

	//a1.栈对象数组的定义

	//date array_1[3];//调用无参构造函数
	//date array_2[3] = { date(2019,10,1),date(2019,10,2) };//按需调用构造函数

	//a2.堆对象数组的定义
	//date *parray_1 = new date[3];//调用无参构造函数

	date *parray_2 = new date[3];//调用无参构造函数

	date *temp = parray_2;

	parray_2[0] = date(2020, 1, 1);
	parray_2[1] = date(2020, 1, 2);
	parray_2[2] = date(2020, 1, 3);



	//b. 对象数组元素访问对象成员的方式(2种)

	for (int i = 0; i < 3; i++)
	{
		
		//array_1[i].display();//直接访问对象成员法


		//array_2[i].display();//直接访问对象成员法


		//(parray_1++)->display();//间接访问对象成员法

		(parray_2++)->display();//间接访问对象成员法
		//循环体执行完本语句后,如果在程序里用delete[]parray_2就会报错,因为
		//此时parray_2不再指向动态数组的首地址,而是第3个元素的地址,所以
		//建议使用直接访问的方式比较稳妥!!!!

		

		
	}

	delete[]temp;

#endif

#if 0
	//---------------------第二块演示:对象的指针----------------------------------

	date s1;

	//1. 探索指针的初始化,建议定义指针变量时务必对其进行初始化,否则后患无穷!!
	date *p = NULL;//如果这里令 date *p=1,就会报错,这里的NULL实际是0,本质上是个地址,即NULL=0=00000000
	cout << "p指向到哪里:" << p << endl;

	p = 0;//这里的0,本质上是个地址,即0=00000000,如果改成p=1,报错,因为1不是内存地址.
	cout << "p指向到哪里:" << p << endl;


	//2.指针的两种用法
	p = &s1;

	s1.getYear();


	(*p).getYear();
	p->getYear();

#endif


#if 0
	//----------------------第三块演示:对象的引用----------------------------------

	date today;

	date &r = today;

	today.display();
	r.display();


	date tomorrow(2030, 10, 1);


	//r自始至终都是today的引用,不会变化
	//通过改变today或r的值,彼此内容都会发生变化
	r = tomorrow;

	today.display();



	//对象引用的核心作用:作为函数的形参
	
	print(today);

#endif

#if 0

	//----------------------第四块演示:.对象作为参数(对象,对象指针,对象引用)----------------------------------

	date day_1(1970, 1, 1);
	date day_2(1970, 1, 1);
	date day_3(1970, 1, 1);
	

	objectAsArgument(day_1, &day_2, day_3);

	day_1.display();//day_1对象没有被修改(数值)
	day_2.display();//day_2对象已经被修改(指针)
	day_3.display();//day_3对象已经被修改(引用)

#endif

	//-----------------------------------Over---------------------------------------------------------------

	system("pause");//如果想查看析构函数被调用情况,请单步调试,一直F10即可.

	return 0;
}

classDemo.cpp — 类的综合演示

/*************************************************
** 功能 : 类的演示  
** 作者 : tsingke
** 时间 : 2019-10-15 / 08:58
***************************************************/

#include <iostream>
#include <cstdlib>
#include <windows.h>

using namespace std;

//设计一个学生结构体

struct student_s
{
	string name;
	int id;
	int age;
	double high;
	double weight;
	double salary;
};

class date
{

public:
	int year;

private:
	
	int month;
	int day;

public:
	void display()
	{
		cout << year << "" << month << "" << day << "" << endl;
	}
	void initi(int y, int m, int d);

	void modifyear();

	int getmonth()
	{
		return month;
	}
};

void date::initi(int y,int m,int d)
{
	year = y;
	month = m;
	day = d;
}


/*----------------------------------*
          Main Function
*-----------------------------------*/

int main()
{


	struct student_s wang;

	wang.name = "wanger";
	wang.id = 2018;
	wang.age = 20;
	wang.high = 1.75;
	wang.weight = 60;
	wang.salary = 7000;


	date today;


	today.initi(2019, 10, 15);

	today.display();


	today.year = 2020;

	cout<<today.getmonth()<<endl;
	

	system("pause");
	
	return 0;
}

Distribution of the objects and object members.cpp — 对象分布规律

/*************************************************
** 功能 : 对象的访问  
** 作者 : tsingke
** 时间 : 2019-10-21 / 22:27
***************************************************/

#include <iostream>
#include <cstdlib>
#include <windows.h>

using namespace std;



class date
{


private:

	int year;
	int month;
	int day;

public:
	void setDate(int y, int m, int d)
	{
		year = y;
		month = m;
		day = d;

	}
	void display()
	{

		cout << "year=" << year << " month= " << month << " day=" << day << endl;
	}

	void address()
	{

		cout << "year的地址:" << &this->year << endl;
		cout << "month的地址:" <<& this->month << endl;
		cout << "day的地址:" << & this->day<< endl;


	}


};

/*----------------------------------*
          Main Function
*-----------------------------------*/

int main()

{

	
	date a;
	date *p =&a;
	
	//1.对象直接访问其内容
	a.setDate(2019, 10, 22);
	a.display();



	(*p).display();


	//2. 指针间接访问对象内容
	p->display();




	//3. 探索类对象内数据成员的存放规律

	date b;
	date c;

	b.setDate(2019, 12, 31);
	c.setDate(2020, 12, 31);

	cout << endl;

	//3.分析对象的分布规律(高地址-低地址)
	cout << "对象b的地址" << &b << endl;
	cout << "对象c的地址" << &c << endl;

	cout << endl;

	//4.分析对象内变量的分布规律(低地址--高地址)
	b.address();
	//c.address();

	system("pause");
	
	return 0;
}

friend-global function.cpp — 友元全局函数

#include <iostream>

using namespace std;

class date
{
    int year;
    int month;
    int day;

public:
    date(int y,int m,int d) ;
    ~date();
    void display();
    friend void birthdayCheck(date &r1,date &r2);// 友元"流浪"函数的声明
};

date::date(int y, int m, int d)
{
   this->year=y;
    this->month=m;
            this->day=d;
   cout<<"this is a constructor function " <<endl;
}

date::~date()
{
   cout<<"this is a deconstrucor"<<endl ;
}

void date::display()
{
   cout<<year<<"年-"<<month<<"月-"<<day<<""<<endl;
}

void birthdayCheck(date &r1,date &r2)
{

    if((r1.year==r2.year)&&(r1.month==r2.month)&&(r1.day==r2.day))
    {
        cout<<"是同一天生日"<<endl;
    }
    else
    {
        cout<<"不是同一天生日"<<endl;
    }
}

int main()
{


    date zhang(2000,10,1);
    date wang(2000,10,1);

    zhang.display();

    wang.display();


    birthdayCheck(zhang,wang);

    return 0;//

}

shallow-deep — 浅拷贝与深拷贝

student.h

#pragma once
class student
{

private:
	int id;
	char *name; //申请动态内存的信号

public:
	//1. 构造函数,析构函数

	student(int id, const char *user_name);

	student(const student &r);

	~student();


	//2. 普通函数
	void display();
};

student.cpp

#include "student.h"
#include <iostream>

using namespace std;


student::student(int id, const char *user_name)
{
	cout << "构造函数被调用" << endl;
	this->id = id;

	if (user_name!=NULL)
	{
		int len = strlen(user_name);

		name = new char[len + 1];

		strcpy(name, user_name);

	}



}

student::student(const student & r)
{
	this->id = r.id;

   // this->name = r.name;//浅拷贝<-----栈上操作

	if (r.name!=NULL)//深度拷贝<---堆上操作
	{
		int len = strlen(r.name);

		this->name = new char[len + 1];

		strcpy(this->name, r.name);
	}
}


student::~student()
{
	cout << "--析构函数被调用--" << endl;
	
	if(name != NULL)
	{
	  delete[] name;
	}

	
}

void student::display()
{
	cout << "学号id  = " << id << endl;

	cout << "姓名name= " << name << endl;


}

main.cpp

/*************************************************
** 功能 : 浅拷贝-深拷贝代码演示  
** 作者 : 
** 版本 : 2019-10-29 / 19:18
** 版权 : GNU General Public License(GNU GPL)
/**************************************************/

#include <iostream>
#include <cstdlib>
#include "student.h"


using namespace std;



/*----------------------------------*
          Main Function
*-----------------------------------*/

int main()
{
	char *name = new char[20];

	strcpy(name, "bill gates");
	
	student zhang(2019,name);

	student wang = zhang;//调用系统默认的拷贝构造函数



	zhang.display();

	wang.display();





	system("pause");
	
	return 0;
}

shallow-deep-copy — 另一种浅拷贝与深拷贝实现

student.h

#ifndef STUDENT_H
#define STUDENT_H

//析构函数的作用:
/***
 *
 * 完成对象销毁前的清理工作,释放构造器申请的堆空间
 * 无返回类型
 * 自动被调用
 * 不能被重载,因为析构函数本身没有任何参数,所以"同名不同参"的条件永远无法被满足)
 */

class student
{
public:
    student();
    student(char*na,int age,int gender);

    student(const student &r);
    ~student();
    void display();

private:
    char *name;
    int age;
    bool gender;
};

#endif // STUDENT_H

student.cpp

#define _CRT_SECURE_NO_WARNINGS
#include "student.h"
#include<cstring>
#include<iostream>

using namespace  std;

// 使用构造函数完成对象的初始化
student::student()
{

}

student::student(char *na, int age, int gender)
{

    cout << "+构造函数被调用" << endl;
    if (na != NULL)
    {
        int len = strlen(na);

        this->name = new char[len + 1];

        strcpy(this->name, na);
    }

    this->age = age;

    this->gender = gender;

}

student::student(const student &r)
{
    cout << "+拷贝构造函数被调用" << endl;

    //系统默认对位拷贝
    //this->name = r.name;//浅拷贝,仅涉及栈上的数据对位拷贝,不涉及堆

    if (r.name!=NULL)//深度拷贝--仅仅针对有堆数据拷贝的情况
    {

        this->name = new char[strlen(r.name) + 1];

        strcpy(name, r.name);
    }


    this->age = r.age;
    this->gender = r.gender;

}

student::~student()
{
    //删除堆空间
    if (this->name != NULL)
    {
        delete[] name;
    }

    cout << "~析构函数被调用" << endl;


}

void student::display()
{
    cout << "name  = " << name << endl;
    cout << "age   = " << age << endl;
    cout << "gender= " << this->gender << endl;

}

main.cpp

#include <iostream>
#include "student.h"
using namespace std;

int main()
{
    char *name =new char[20];

    name="Bill Gates";

    student stu1(name,60,1);
    stu1.display();

    student stu2=stu1;
    stu2.display();






    return 0;
}

第四章:类与对象(下)— static 与 const

内容说明:本章深入探讨类的static成员和const成员,包含const静态与全局常量、常成员函数、常对象、静态成员变量、静态成员函数。

const — 常量

const_demo_1(常量const本质剖析).cpp

/*************************************************
** 功能 : const本质:const栈常量与const全局区常量 能否被修改?
** 作者 : tsingke
** 时间 : 2019-11-11 / 23:36
***************************************************/

#include <iostream>
#include <cstdlib>
#include <windows.h>

using namespace std;


const int global = 100;

/*----------------------------------*
		  Main Function
*-----------------------------------*/

int main()
{

#if 1
	//情形1: const修饰的栈上的常量,通过指针可以间接实现对其修改

	const int  local = 10;//下面程序所有的local在编译时都被替换为10

	cout << "const local = " << local << endl;

	//意图通过指针修改这个常量

	int *p1 = (int*)(&local);

	*p1 = 20;

	cout << "const local = " << *p1 << endl;

	cout << "local地址   = " << &local << endl;
	cout << "p1指向的地址 = " << p1 << endl;

#endif

	//---------------------------------------------

#if 0
//情形2:const修饰的全局区上的常量,通过指针无法对其进行修改(编译时会报异常)

	int *p2 = (int*)(&global);

	cout << "const global = " << global << endl;

	*p2 = 200;

	cout << "const global = " << *p2 << endl;

	cout << "global地址  = " << &global << endl;
	cout << "p2指向的地址 = " << p2 << endl;

#endif


	system("pause");

	return 0;
}

const_demo_2(常成员变量,常函数,常对象).cpp

/*************************************************
** 功能 : 常数据成员,常成员函数,常对象  
** 作者 : tsingke
***************************************************/

#include <iostream>
#include <cstdlib>
#include <windows.h>

using namespace std;

class circle
{

private:

	double R;
	const double pi;//常成员变量
	static int TotalCount;
public:

	circle(double r = 0):pi(3.1415926)
	{
		this->R = r;
		
	}


	//修改半径
	double getR()     //普通函数
	{
		cout << "getR()被调用" << endl;
		return R;
	}

	//访问半径
	double getR() const  //常成员函数,重装函数
	{
		cout << "getR()const被调用" << endl;

		//setR(2);//报错,因为常函数不能访问普通非常函数,只能常对常访问
		return R;
	}

	//访问半径
	void setR(double r)
	{
		R = r;
	}

	//输出面积
	double area()
	{
		getR();//普通函数可以访问常函数
		return pi * R*R;
	}

	//输出周长
	double circumstance()
	{
		return 2 * pi*R;
	}

};

int circle::TotalCount = 0;//定义初始化静态成员变量


/*----------------------------------*
          Main Function
*-----------------------------------*/

int main()
{


	circle A;//普通的对象
	const circle B(3.5);//常对象,带参初始化(务必要初始化)
	const circle C;//常对象,采用构函默认值初始化

	cout<< "A.getR() = "<< A.getR()<<endl;//普通对象调用对应的非常函数,如果非常函数不存在,就调用常函数
	cout<< "B.getR() = " <<B.getR()<<endl;//常对象调用常函数

	
	A.setR(5.4);//正确,普通对象可访问所有类内普通函数
	//B.setR(12);//报错,常对象不能访问普通函数,必须访问常成员函数



	system("pause");
	
	return 0;
}

static — 静态成员

complex.h

#ifndef COMPLEX_H
#define COMPLEX_H

class complex
{

private:
  double x;
  double y;
  static int count;//私有的静态成员变量

public:
  complex(int px,int py);
  ~complex();
  void display();

  static int s;//公有的静态成员变量
  static void showcount();//
};

//int complex::s=0;    //类外初始化,务必注意,如果将类采用多文件编程时,静态成员变量的定义不要放在.h文件中,放在.cpp文件中,否则会引发多重定义问题.
//int complex::count=0;//类外初始化,必注意,如果将类采用多文件编程时,静态成员变量的定义不要放在.h文件中,放在.cpp文件中,否则会引发多重定义问题.

#endif // COMPLEX_H

complex.cpp

#include "complex.h"
#include <iostream>

//初始化静态数据成员
int complex::s=0;    //类外初始化,务必注意,如果将类采用多文件编程时,静态成员变量的定义不要放在.h文件中,放在.cpp文件中,否则会引发多重定义问题.
int complex::count=0;


//-------c/c++中的static本质:持久化存储,实现数据共享功能-------------
using namespace std;

//extern int global;

complex::complex(int px, int py):x(px),y(py)
{
  cout<<"Constructor is called"<<endl;
  count++;
  cout<<"cout = "<<count<<endl;

}

complex::~complex()
{
  cout<<"destructor is called"<<endl;
  count--;
  cout<<"cout = "<<count<<endl;

}

void complex::display()
{
  cout<<"x = "<<x<<endl;
  cout<<"y = "<<y<<endl;

  showcount();//普通函数可以直接访问静态函数

}

void complex::showcount()//本质是类外的全局函数
{
   cout<<"count = "<<count<<endl;

  //this->x=2;//静态成员函数无法访问非静态成员

   //display();//会报错,不允许在静态函数访问非静态函数(因为普通函数背后是对象)

}

main.cpp

#include <iostream>
#include "complex.h"
using namespace std;


//int global=10;   //可以在整个程序的多个文件内共享的全局变量,只要其他位置将其声明为外部变量即可,exter int global;

static int s_ga=0;//仅在本文件内进行共享的全局变量,外部文件无法访问外联性,external link

void func(int t)
{
  static int s_la=0;//static 修饰局部变量,la此时就具有了持久化存储能力,直到程序结束一直存在;初始化工作只在开始执行1次,之后不再初始化

  s_la=s_la+t;

  cout<<"s_la= "<<s_la<<endl;

}

int main()
{
 //-------------------1-----------------------
#if 1
  //1. 测试静态全局变量的本质

  s_ga=2;

  s_ga++;

  cout<<"s_ga="<<s_ga<<endl;

#endif

 //-------------------2-----------------------
#if 1
  //2. 测试静态局部变量的本质

  for (int i = 0; i < 10; ++i)
    {
      func(i);
    }
  cout << "Hello World!" << endl;
#endif

  //------------------3------------------------

#if 1

  //3. static 在类中的使用(静态数据成员、静态成员函数)

  //静态变量:本质为外部的全局变量,现在将其拉到类内,实现封装
  //静态函数:本质为外部的全局函数,专门为访问类内静态变量而设置。

  complex ca(2,5);
  complex cb(1,4);


  //3.1 类直接访问公有静态数据成员
  cout<<"complex::s= "<<complex::s<<endl;

  //3.1 对象访问公有静态数据成员
  cout<<"ca.s = "<<ca.s<<endl;
  cout<<"cb.s = "<<cb.s<<endl;

  //~~~~

  //3.2 类通过静态成员函数访问私有静态数据成员(专门为类服务的)
  complex::showcount();

  //3.2 对象通过访问静态成员函数访问私有静态数据
  ca.showcount();
  ca.display();

#endif

  //cout<<"complex::count"<<complex::count<<endl;
  return 0;
}

第五章:类关系—继承

内容说明:本章研究类与类之间的继承关系,包含三种继承方式、同名冲突、多继承构造函数调用次序、菱形继承、赋值兼容性。

chapt5_class relations/inheritance/README.md

1-inheritance_定义和三种继承理解.cpp

/*************************************************
** 功能 : 类三种继承的定义形式,三种继承关系的深刻理解 
** 作者 : tsingke
** 时间 : 2019-11-25 / 21:37
***************************************************/

#include <iostream>
#include <cstdlib>
#include <windows.h>

using namespace std;


class A            //作为基类
{
//------------------成员数据------------------

public:
	int a_pub;
protected:
	int a_pro;
private:
	int a_pri;
//------------------成员函数------------------
public:
	A(int pub=0, int pro=0, int pri=0)  //有参构造
	{
		cout << "A() is called" << endl;

		this->a_pub = pub;
		this->a_pro = pro;
		this->a_pri = pri;


	}
	~A()//析构函数
	{
		cout << "~A() is called" << endl;
		getchar();

	}

	void dispaly()
	{
		cout << "基类对象成员数据:" << a_pub << " " << a_pro << " " << a_pri<<endl;
	}


};

//--------------------研究三种不同的继承方式------------------------
class B:public A  //公有继承
{
private:
	int bb;

public:
	B(int b=2):A(2,2,2)
	{
		this->bb = b;
		cout << "B() is called" << endl;
	}
	~B()
	{
		cout << "~B() is called" << endl;
		getchar();

	}

	void display()//探索公有继
	{
		//基类数据传承探索
		a_pub = 200;//a_pub仍为公有数据,子类内可以直接访问
		a_pro = 200;//a_pro仍为保护数据,子类内可以直接访问
		//a_pri = 200;//报错,基类私有成员在子类不可见

		//基类函数传承探索
		A::dispaly();
		cout << "自身添加数据成员: bb = "<<bb << endl;


	}

};

class C: protected A //保护继承
{

private:
	int cc;
public:
	C(int c=3):A(3,3,3)
	{
		cout << "C() is called" << endl;

		this->cc = c;
	}
	~C()
	{
		cout << "~C() is called" << endl;
		getchar();


	}

	void display()//探索保护继承
	{
		//基类数据传承探索
		a_pub = 300;//a_pub变为保护数据,类内可以直接访问
		a_pro = 300;//a_pro变为保护数据,类内可以直接访问
		//a_pri = 300;//报错,基类私有成员在子类不可见

		//基类函数传承探索
		A::dispaly();
		cout << "自身添加数据成员: cc = " << cc << endl;


	}
};

class D : private A  //私有继承
{

private:
	int dd;
public:
	D(int d = 4): A(4, 4, 4)
	{
		cout << "D() is called" << endl;

		this->dd = d;
	}

	~D()
	{
		cout << "~D() is called" << endl;
		getchar();

	}
	void display()//探索私有继承
	{
		//基类数据传承探索
		a_pub = 400;//a_pub变为私有数据,子类内可以直接访问
		a_pro = 400;//a_pro变为私有数据,子类内可以直接访问
		//a_pri = 400;//报错,基类私有成员在子类不可见

		//基类函数传承探索
		A::dispaly();
		cout << "自身添加数据成员: dd = " << dd << endl;


	}
};

/*----------------------------------*
          Main Function
*-----------------------------------*/

int main()
{

	//功能1:通过比较类的大小,证明无论哪种继承方式都会全盘接受基类成员,包括私有的成员

#if 1

	cout << "基类A的大小为: " << sizeof(A) << endl;
	cout << "--类B的大小为: " << sizeof(B) << endl;
	cout << "--类C的大小为: " << sizeof(C) << endl;
	cout << "--类D的大小为: " << sizeof(D) << endl;

	cout << "---------------------------------" << endl;

#endif
	

	//功能2:构造函数和析构函数的调用
#if 1
	A a;
	cout << "---------------" << endl;

	B b;
	cout << "---------------" << endl;


	C c;
	cout << "---------------" << endl;


	D d;
	cout << "---------------" << endl;

#endif

	//功能3:三种继承的使用(类外访问探索)

#if 0
	//------------类B--公有继承--类A---------------
	B b;//派生类B的对象

	  b.a_pub = 200; //正确, 子类内仍然为公有成员,类内外均可访问
	//b.a_pro = 200; //错误,子类内仍然为保护成员,类内可直接访问,类外不可以
	//b.a_pri = 200; //错误,基类私有成员在子类内外均不可见

	//b.dispaly();   //正确,访问的是子类自身的公有成员
	//b.A::dispaly();//正确, 子类内函数仍然为公有成员,类内外均可访问

#endif
	
#if 0
	//------------类C--保护继承--类A---------------
	C c;//派生类C的对象
	//c.a_pub = 300;//错误,变为子类保护成员,无法类外直接访问
	//c.a_pro = 300;//错误,变为子类保护成员,无法类外直接访问
	//c.a_pri = 300;//错误,基类私有成员在子类内外均不可见

	//c.display();    //正确,访问的是子类自身的公有成员
	//c.A::dispaly(); //错误,变为子类的保护函数,不可类外访问

	
#endif

#if 0
	//------------类D--私有继承--类A---------------

	D d;//派生类D的对象

	//d.a_pub = 400; //报错,变为子类的私有成员,无法类外直接访问
	//d.a_pro = 400; //报错,变为子类的私有成员,无法类外直接访问
	//d.a_pri = 400; //报错,基类私有成员在子类内外均不可见

	//d.dispaly();    //报错,变为子类私有成员,无法类外直接访问
	//d.A::dispaly(); //错误,继承后变为子类私有函数,无法类外直接访问

#endif
	
	system("pause");
	
	return 0;
}

2-inheritance-父子同名与数据访问方式.cpp

/*************************************************
** 功能 : 类的继承中,父子类间同名冲突问题(单继承)  
** 作者 : tsingke
** 时间 : 2019-11-25 
***************************************************/

#include <iostream>
#include <cstdlib>
#include <windows.h>

using namespace std;


class base
{
private:
	int a;
public:
	base(int _a):a(_a) 
	{
		this->a = _a;;
	}
	~base() {}
	int get() { return a; }

};

class derived : public base
{
private:
	int a;
public:
	derived(int _a) :base(_a*10)
	{
		this->a = _a;
	}

	~derived() {}

	int get() { return a; }

};

/*----------------------------------*
          Main Function
*-----------------------------------*/

int main()
{

	base b(10);
	derived d(20);


	//1.冲突解决: 通过域名解析符来访问被子类遮挡的父类的同名成员
	cout<<"d.get()= "<< d.get()<<endl;     //只能访问派生类的get函数(掩盖了基类的get函数)

	cout<<"d.base::get()= "<<d.base::get()<<endl;//访问父类中的同名函数,通过域名解析的方法

	//2.基类指针用法

	cout << "------基类指针指向派生类对象----------" << endl;
	base *pb;
	pb = &d;
	cout<<"pb->get() = "<<pb->get()<<endl;//通过基类指针指向派生类对象, 基类指针仅能访问到被派生类继承过去的成员数据或成员函数
	
	//3. 基类引用用法
	cout << "------基类引用,引用派生类对象----------" << endl;

	base &r = d;
	cout <<" r.get() = "<< r.get() << endl;//


	system("pause");
	
	return 0;
}

3-inheritance-多继承与基类构函调用次序问题.cpp

/*************************************************
** 功能 : 类的多继承-同名冲突问题/基类构函调用次序问题 
** 作者 : tsingke 
***************************************************/

#include <iostream>
#include <cstdlib>
#include <windows.h>

using namespace std;

class base1
{
public:
	int a;
	base1(int _a)
	{
		cout << "base1() is called" << endl;
		this->a = _a;
	}
	~base1()
	{
		cout << "~base1() is called" << endl;
		getchar();

	}
	void print()
	{
		cout << "base1的a = " << a << endl;
	}
};

class base2
{
public:
	int a;
	base2(int _a)
	{
		cout << "base2() is called" << endl;
		this->a = _a;
	}
	~base2()
	{
		cout << "~base2() is called" << endl;
		getchar();

	}
	void print()
	{
		cout << "base2的a = " << a << endl;
	}

};



//构造函数调用次序与下面"定义派生类"时各个基类出现的先后顺序有关,与其在文件中定义的顺序无关
class derived : public base2, public base1
{
public:
	int a;
public:
	derived(int _a):base1(_a * 2),base2(_a * 3)

	{
		cout << "derived() is called" << endl;

		this->a = _a;
	}
	~derived()
	{
		cout << "~derived() is called" << endl;
		getchar();

	}
	void print()
	{
		cout << "derived的a = " << a << endl;
	}
};

/*----------------------------------*
          Main Function
*-----------------------------------*/

int main()
{


	//1. 派生类访问自己的数据

	derived d(1);

	cout << "d.a = " << d.a << endl;

	d.print();//优先访问派生类的函数

	cout << "-----------------------" << endl;

	//2.派生类对象访问继承自父类的数据成员

	cout << "d.base1::a = " << d.base1::a << endl;
	cout << "d.base2::a = " << d.base1::a << endl;


	cout << "-----------------------" << endl;

	//3. 访问基类中的同名函数

	d.base1::print();//访问基类1中的同名函数

	d.base2::print();//访问基类2中的同名函数





	system("pause");
	
	return 0;
}

4-inheritance-菱形继承sofabed.cpp

/*************************************************
** 功能 : 类的多继承:菱形继承解决方案-虚继承 
** 作者 : tsingke 
** 提示 : 绘制派生类成员关系图,不迷路
***************************************************/

#include <iostream>

using namespace std;

//定义家具类(祖先类)
class Furnitrue
{
public:
    void Show()
    {
        cout <<"m_weight " << m_weight << endl;
        cout <<"m_color" << m_color << endl;
    }
	//一个类如果想要让别人来继承,同时要保证自己数据的封装性,那么可以将其定义为protected类型
protected:
    int m_weight;//家具的重量数值(公共属性)
    int m_color; //家具的颜色数值(公共属性)
};

//1.定义沙发类
class Sofa : virtual public Furnitrue
{
public:
    Sofa(int x=50, int y=100)
    {
        m_weight = x;
        m_color = y;
    }
    void sit()
    {
        cout << "Sofa can sit" << endl;
    }

};

//2.定义床类
class Bed : virtual public Furnitrue
{
public:
    Bed(int x=50, int y=100)
    {
        m_weight = x;
        m_color = y;
    }
    void sleep()
    {
        cout << "Bed can sleep" << endl;
    }
};

//3. 定义沙发床类
class SofaBed : public Sofa, public Bed
{
public:
    SofaBed(int x, int y)
    {
        m_weight = x;//只有一份
        m_color = y;//只有一份
    }
};

int main()
{
    SofaBed sb(100, 999);
    sb.sit();
    sb.sleep();
    sb.Show();
    return 0;
}

5-inheritance-赋值兼容.cpp

#include <iostream>

using namespace std;

//赋值兼容(有亲缘关系的数据才可以赋值,晚辈赋值给长辈)

//1派生类对象可以赋值给基类对象
//2派生类对象可以初始化基类的引用
//3派生类对象的地址可以赋值给指向基类的指针

//定义图形类
class Shape
{
public:
    Shape(int x=0, int y=0)
        :m_x(x),m_y(y)
    {

    }
    void Draw()
    {
        cout << "Shape::" << "(" << m_x << "," << m_y << ")" << endl;
    }
protected:
    int m_x;
    int m_y;
};

//定义圆类
class Circle : public Shape
{
public:
    Circle(int x=0, int y=0, int r=0)
        :Shape(x,y),m_radius(r)
    {

    }
    void Draw()
    {
        cout << "Circle::" << "(" << m_x << "," << m_y << ")" << "radius" << m_radius << endl;
    }
protected:
    int m_radius;
};

int main()
{
    //1.派生类对象可以赋值给基类对象
    //Shape s(1,2);
    //s.Draw();
    //Circle c(3,4,5);
    //c.Draw();
    //
    //s = c;
    //s.Draw();


//2.派生类对象可以初始化基类的引用
//    Circle c(3,4,5);

//    Shape & rs = c;
//    rs.Draw();


    //3.派生类对象的地址可以赋值给指向基类的指针
    //Circle c(3,4,5);
    //Shape *ps = &c;
    //ps->Draw();




    //int a = 10;
    //int *pi = &a;
    //char *pc = &a; //这样是不安全的
    //
    //char ch = 'a';
    //int *pi = &ch;//这样是不安全的





    return 0;
}

第六章:多态性

1-静态多态性

内容说明:静态多态性通过函数重载实现,包含普通函数的重载和运算符重载(成员函数法、友元函数法)。

complex.h

#ifndef COMPLEX_H
#define COMPLEX_H

#include <iostream>
using namespace std;

class complex
{
private:
    double real;
    double imag;

public:
    //===================静态多态: 函数重载========================
    complex();
    complex(double r, double i);//构造函数
    complex(const complex &r);
     ~complex();

    void print();
    void print()const;



    //===============静态多态: 运算符重载1-成员函数法===============

     //a.重载加法运算符+(双目运算符)
    complex operator+(const complex &other);


    //b.重载赋值运算符=(双目运算符)-类内重载

    complex operator=(const complex &other);

     //c.重载前++运算符(单目运算符)-类内重载,类外重载均可
    complex operator++();


     //d.重载后++运算符(单目运算符)-类内重载
    complex operator++(int);


    //e.重载函数调用运算符()运算符(单目运算符)-类内重载
    double operator()();

   //===============静态多态: 运算符重载2-友元函数法===============

    //-重载输出运算符<< : 双目运算符,格式"cout<<" 左侧是一个输出流对象cout"
    friend ostream& operator<<(ostream &out, complex &t);

};


#endif // COMPLEX_H

complex.cpp

#include "complex.h"



//-----------------------成员函数-------------------------

complex::complex()
{

}

complex::complex(double r, double i)
{
    this->real =r;
    this->imag =i;
}

complex::complex(const complex &r)
{
    this->real =r.real;
    this->imag = r.imag;
}

complex::~complex()
{

}

void complex::print() const
{


}

complex complex::operator+(const complex &other)
{

    complex temp;

    temp.real = this->real + other.real;
    temp.imag = this->imag + other.imag;

    return  temp;

}

//赋值运算符=
complex complex::operator=(const complex &other)
{
    this->real = other.real;
    this->imag = other.imag;
}

//前++
complex complex::operator++()
{
    ++this->real;
    ++this->imag;

    return *this;

}

//后++
complex complex::operator++(int)
{
    complex temp;//

    temp.real = this->real++;
    temp.imag=this->imag++;

    return  temp;

}

//函数调用符
double complex::operator()()
{
    double sum = this->real * this->real + this->imag *this->imag;

    return  sum;

}


//-----------------------友元函数-------------------------
ostream & operator<<(ostream &out, complex &t)
{
    out<<t.real<<"+" <<t.imag<<"i"<<endl;
}

main.cpp

/*-------------------------------------
 * 功能: 类的静态多态性(函数重载+运算符重载)
 * 作者: tsingke
-------------------------------------*/


//静态多态: 函数重载(同名不同参) + 运算符重载(4种)

#include <iostream>
using namespace std;

#include "complex.h"


//--------------主函数---------------

int main()
{

    //定义复数类的对象
    complex a(6,6);
    complex b(8,8);
    complex c,d,e;


    //1. 重载输出运算符<<, 输出大对象 (双目运算符)
    cout<<"a="<<a<<endl;
    cout<<"b="<<b<<endl;
    cout<<"c="<<c<<endl;



    //2. 重载加法运算符+ (双目运算符),
    c = a + b;//a.operator+(b);
    cout<<c;



    //3. 重载赋值运算符= (如果对象不涉及堆内存资源,不建议重载赋值运算符,使用系统提供的就可以)
    c = a;
    cout<<c<<endl;



    //4. 重载函数调用运算符()  (多目运算符)
    cout<<a()<<endl;//输出距离real^2 +imag^2;





    //5.1 重载后++, 对象a++(后加加)-(单目运算符)

    d=a++;
    cout<<"d=a++; d = "<<d<<endl;



    //5.2 重载前++,对象++b(前加加)-(单目运算符)
    e=++b;
    cout<<"e=++b; e = "<<e<<endl;




    return 0;
}

2-动态多态性

内容说明:动态多态性通过虚函数实现,包含赋值兼容性、虚函数原理、虚析构函数、纯虚函数与抽象类,以及游戏实战案例。

1-预备工作-赋值兼容性.cpp

/*************************************************
** 功能 : 动态多态性--指哪打哪如何实现
** 作者 : tsingke
***************************************************/

#include <iostream>
#include <cstdlib>

using namespace std;
class base
{

private:
  int a;
  int b;
  int c;
public:
  base()
  {
    cout<<"base() is called"<<endl;

  }
  void display()
  {
    cout<<"base-display() is called "<<endl;

  }
};

class derive: public base
{
private:
  int x,y,z;
public:
  derive()
  {
    cout<<"derive() is called"<<endl;
  }
};


/*----------------------------------*
          Main Function
*-----------------------------------*/

int main()
{


  base father;

  derive son;



  //---------探索赋值兼容性:3种类型---------

  father = son;//赋值兼容性1

  //son = father;//错误, 父类对象不能赋值给派生类对象

  base *p = &son;//赋值兼容性2

  base &r = son;//赋值兼容性3



  father.display();//调用父类函数

  p->display();    //调用父类内的函数

  r.display();     //调用父类内的函数


  /*
   * 赋值兼容性存在的问题:无法通过父类指针访问到子类新添加的同名函数
   * 解决方法:在基类内设置同名函数为虚函数,即可实现"指哪打哪"的效果
   **/



  return 0;
}

2-动态多态性-虚函数-指哪打哪.cpp

/*************************************************
** 功能 : 动态多态性--只要公有继承,长相相同,就能指哪打哪
** 作者 : tsingke
***************************************************/

#include <iostream>
#include <cstdlib>

using namespace std;
class base
{

private:
  int a;
  int b;
  int c;
public:
  base()
  {
    cout<<"base() is called"<<endl;

  }

  virtual void display()
  {
    cout<<"base-display() is called "<<endl;

  }
};

class derive: public base
{
private:
  int x,y,z;
public:
  derive()
  {
    cout<<"derive() is called"<<endl;
  }

  void display()//由于父类同名函数display()为虚函数,因此,子类同名函数自动变为虚函数
    {
      cout<<"derive-display() is called "<<endl;

    }
};


/*----------------------------------*
          Main Function
*-----------------------------------*/

int main()
{


  base father;

  derive son;



  //--------虚函数实现动态多态性---------

  father = son;//赋值兼容性1

  //son = father;//错误, 父类对象不能赋值给派生类对象

  base *p = &son;//赋值兼容性2

  base &r = son;//赋值兼容性3



  father.display();//调用父类函数

  p->display();    //调用子类内的函数(p指向子类对象,调用子类函数)

  r.display();     //调用子类内的函数(r引用子类对象,调用子类函数)


  /*
   * 赋值兼容性存在的问题:无法通过父类指针访问到子类新添加的同名函数
   * 解决方法:在基类内设置同名函数为虚函数,即可实现"指哪打哪"的效果
   **/



  return 0;
}

3-动态多态性-虚函数原理挖掘.cpp

/*************************************************
** 功能 : 动态多态性--虚函数实现原理
** 作者 : tsingke
***************************************************/

#include <iostream>
#include <cstdlib>

using namespace std;
class base
{

private:
	int a;
public:
	base()
	{
		cout << "base() is called" << endl;

	}

	virtual void display()
	{
		cout << "base-display() is called " << endl;

	}
};

class derive : public base
{
private:
	int x;
public:
	derive()
	{
		cout << "derive() is called" << endl;
	}

	void display()//由于父类同名函数display()为虚函数,因此,子类同名函数自动变为虚函数
	{
		cout << "derive-display() is called " << endl;

	}
};


/*----------------------------------*
		  Main Function
*-----------------------------------*/

int main()
{


	base father;

	derive son;


	//-----虚函数通过设置虚函数表实现-----

	cout << "---------------------" << endl;

	cout << "base 类大小为:  " << sizeof(base) << endl;
	cout << "derive类大小为: " << sizeof(derive) << endl;

	cout << "---------------------" << endl;



	//--------虚函数实现动态多态性---------

	father = son;//赋值兼容性1

	//son = father;//错误, 父类对象不能赋值给派生类对象

	base *p = &son;//赋值兼容性2

	base &r = son;//赋值兼容性3



	father.display();//调用父类函数

	p->display();    //调用子类内的函数(p指向子类对象,调用子类函数)

	r.display();     //调用子类内的函数(r引用子类对象,调用子类函数)


	/*
	 * 赋值兼容性存在的问题:无法通过父类指针访问到子类新添加的同名函数
	 * 解决方法:在基类内设置同名函数为虚函数,即可实现"指哪打哪"的效果
	 **/


	getchar();

	return 0;
}

4-动态多态性-虚析构函数.cpp

/*************************************************
** 功能 : 动态多态性--虚析构函数(一虚全虚)
** 作者 : tsingke
***************************************************/

#include <iostream>
#include <cstdlib>

using namespace std;

//--------------------父类----------------------------

class base
{

private:
	int a;
public:
	base()
	{
		cout << "base() is called" << endl;

	}
	//~base(){}// 
	virtual ~base()
	{
		cout << "~base() is called" << endl;
	}

	virtual void print()
	{
		cout << "base-print() is called" << endl;
	}


};

//--------------------子类----------------------------
class derive : public base
{
private:
	int *id;
public:
	derive()
	{
	
		id = new int[10];
		cout << "derive() is called" << endl;
	}
	~derive()//如果基类析构函数为虚函数,则子类的析构函数全都自动变为虚函数
	{
		cout << "~derive() is called" << endl;
		if (id!=NULL)
		{
			delete[] id;
		}
	}

	virtual void print() //公有继承,长相相同
	{
		cout << "derive-print() is called" << endl;
	}

};


/*----------------------------------*
		  Main Function
*-----------------------------------*/

int main()
{


	base *p = new derive; //通过基类指针创建无名对象

	p->print();          // 通过虚函数实现"指哪打哪"的目的

	delete p;             //通过基类指针释放无名对象


	return 0;
}

5-动态多态性-纯虚函数.cpp

/*************************************************
** 功能 : 纯虚函数与抽象类  
** 作者 : 张庆科
** 时间 : 2019-12-9
***************************************************/

#include <iostream>
#include <cstdlib>
#include <cmath>    //不要落掉,调用其sqrt()函数
#include <windows.h>

using namespace std;


//----------------抽象类: 图形类-------------------

class shape
{
public:
	virtual double circumstance() = 0;

	virtual double area() = 0; //含有纯虚函数的类就是抽象类

};

//----------------具体类:正方形类-------------------

class squre:public shape
{
private:
	double a;

public:
	squre(int _a) :a(_a)
	{
		cout << "生成正方形对象, 边长 = " << a << endl;
	}
	~squre() {}

	double circumstance()//基类同名为虚函数,子类相同函数自动变为虚函数(公有继承,长相相同)
	{
		return 4 * a;
	}

	double area()       //基类同名为虚函数,子类相同函数自动变为虚函数(公有继承,长相相同)
	{
		return a * a;
	}

};

//----------------具体类:三角形类-------------------

class triangle:public shape
{
private:
	double a, b, c;
public:
	triangle(double _a, double _b, double _c) :a(_a), b(_b), c(_c) 
	{

		if ((a+b<=c) || (a+c<=b) || (b+c <=a))
		{
			cout << "无法构成三角形,请重新输入三条边:" << endl;
			cin >> a;
			cin >> b;
			cin >> c;
		}

		cout << "生成三角形对象, 边长 = " << a <<" "<< b << " " << c<<endl;



	}
	~triangle() {}

	double circumstance() //基类同名为虚函数,子类相同函数自动变为虚函数(公有继承,长相相同)
	{
		return a + b + c;
	}

	double area()        //基类同名为虚函数,子类相同函数自动变为虚函数(公有继承,长相相同)
	{
		double p = 0.5 * circumstance();

		return sqrt(p*(p - a)*(p - b)*(p - c));

	}

};

//全局函数,输出某个图形的周长和面积
void display(shape *p)
{


	cout << "周长为: " << p->circumstance() << endl;//多态语句(指哪打哪)
	cout << "面积为: " << p->area() << endl;        //多态语句(指哪打哪)

	cout << "------------------------------" << endl;
}



/*----------------------------------*
          Main Function
*-----------------------------------*/

int main()
{

	squre squ(10);         //正方形类对象

	triangle tri(3, 4, 5); //三角形类对象


	//------------1. 抽象类的特性探索----------

	//shape sha;  // 错误, 不可以生成抽象类的对象
	cout << "sizeof(shape) = " << sizeof(shape) << endl;//可以计算抽象类大小

	shape *p;     // 正确, 可以建立抽象类的指针变量
	shape &r = squ;//正确, 可以建立抽象类的对象引用,引用的是派生类对象


	//-----------2. 动态多态特性探索-----------
	cout << endl;

	cout << "正方形的周长和面积:"<<endl;
	display(&squ);//输出正方形的周长和面积, 指哪打哪

	cout << "三角形周长和面积:"<<endl;
	display(&tri);//输出三角形的周长和面积, 指哪打哪

	


	system("pause");
	
	return 0;
}

游戏王者争霸-虚函数与动态多态.cpp

/*************************************************
** 功能 : 动态多态实践应用: 王者争霸游戏模拟  
** 作者 : tsingke
/**************************************************/


//动态多态:借助虚函数实现

//动态多态条件: 公有继承(public), 原型相同(基类与子类某个函数原型相同) 
//实现的结果  :指哪打哪

#include <iostream>
#include <cstdlib>
#include <ctime>

using namespace std;

int killDragon = 0;
int killLion = 0;
int killTiger = 0;

const int MaxDragon = 5;
const int MaxLion = 20;
const int MaxTiger = 30;

const int iter = 100;

//-------------------基类:所有游戏角色的基类------------------------
class Canimal
{
protected:

	double lifeValue; // 生命力,自身的寿命
	double power;     // 攻击力,对其他动物


public:
	virtual void Attack(Canimal *other) {};  //虚函数: 自己主动攻击别人
	virtual void Fightback(Canimal *own) {};//虚函数: 攻击别人时被别人反击自己
	virtual void Hurted(int power) {};       //虚函数: 自己被别人主动攻击

};

//-------------------具体类: dragon龙类------------------------
class Cdragon : public Canimal
{
public:
	Cdragon(double _value = 100, double _power = 50)
	{
		this->lifeValue = _value;
		this->power = _power;
	}

	//自己被别人攻击
	void Hurted(int power)
	{

		this->lifeValue -= power;
		if (lifeValue <= 0)
		{
			cout << "龙被打死了 ";
			killDragon++;
		}

	}

	//被反击:攻击别人时,被别人反击
	void Fightback(Canimal *p)
	{
		p->Hurted(0.5*power);

	}

	//主动攻击: 自己攻击别人,使别人受伤,自己也受到一些对方的反击伤害
	void Attack(Canimal *other)
	{
		other->Hurted(power);  //攻击别人,使别人受伤
		other->Fightback(this);//被别人反击,自己也受伤
	}

};

//-------------------具体类: CLion 狮子类------------------------

class Clion : public Canimal
{
public:
	Clion(double _value = 100, double _power = 30)
	{
		this->lifeValue = _value;
		this->power = _power;
	}


	//自己被别人攻击
	void Hurted(int power)
	{

		this->lifeValue -= power;
		if (lifeValue <= 0)
		{
			cout << "狮子被打死了 ";
			killLion++;
		}

	}

	//被反击:攻击别人时,被别人反击
	void Fightback(Canimal *p)
	{
		p->Hurted(0.5*power);

	}

	//主动攻击: 自己攻击别人,使别人受伤,自己也受到一些对方的反击伤害
	void Attack(Canimal *other)
	{
		other->Hurted(power);  //攻击别人,使别人受伤
		other->Fightback(this);//被别人反击,自己也受伤

	}

};
//-------------------具体类: CTiger 老虎类------------------------
class Ctiger : public Canimal
{
public:
	Ctiger(double _value = 100, double _power = 20)
	{
		this->lifeValue = _value;
		this->power = _power;
	}


	//自己被别人攻击
	void Hurted(int power)
	{

		this->lifeValue -= power;
		if (lifeValue <= 0)
		{
			cout << "老虎被打死了 ";
			killTiger++;
		}

	}

	//被反击:攻击别人时,被别人反击
	void Fightback(Canimal *p)
	{
		p->Hurted(0.5*power);

	}

	//主动攻击: 自己攻击别人,使别人受伤,自己也受到一些对方的反击伤害
	void Attack(Canimal *other)
	{
		other->Hurted(power);  //攻击别人,使别人受伤
		other->Fightback(this);//被别人反击,自己也受伤
	}

};



//=============================主函数================================
int main()
{

	srand((unsigned)time(NULL));

	//1. 初始化一群动物对象
	Cdragon dragon[MaxDragon];//龙类对象数组
	Clion lion[MaxLion];                //狮子类对象数组
	Ctiger tiger[MaxTiger];            //老虎类对象数组

	//2. 动物开始随机厮杀
	cout << "王者争霸游戏已开启,请按任意键开始>>>>>" << endl;
	getchar();

	for (int i = 0; i < iter; ++i)
	{
		cout << "开始第" << i + 1 << "轮厮杀: ";

		switch (rand() % 2)
		{
		case 0: //龙攻击狮子
		{
			//随机选择一个龙和一头狮子
			int id1 = rand() % MaxDragon;
			int id2 = rand() % MaxLion;

			dragon[id1].Attack(&lion[id2]);
		}

		break;
		case 1: //狮子攻击老虎
		{
			//随机选择一个狮子和一只老虎
			int id1 = rand() % MaxLion;
			int id2 = rand() % MaxTiger;

			lion[id1].Attack(&tiger[id2]);
		}  break;

		case 2: // 老虎攻击龙
		{
			//随机选择一个老虎和一条龙
			int id1 = rand() % MaxTiger;
			int id2 = rand() % MaxDragon;

			tiger[id1].Attack(&dragon[id2]);
		}  break;

		}//switch

		cout << "kill掉" << (killDragon + killLion + killTiger) << "个怪物" << endl;



	}//for


	cout << "-------------------------" << endl;
	cout << "游戏结束!" << endl<<endl;

	cout << "共kill掉" << killDragon << "条龙" << endl;
	cout << "共kill掉" << killLion << "头狮" << endl;
	cout << "共kill掉" << killTiger << "只虎" << endl;


	system("pause");
	return 0;
}


上一篇
恋爱技巧·异地篇
下一篇
【百题通关参考答案】面向对象程序设计辅导练习题参考答案