第一章:从面向过程到面向对象的过渡案例
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();};
#endifPSO.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);
#endiffunction.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);
#endifscore.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 — 测试数据
6201720398 zhang 84.7 96201720224 wang 78 86201711034 zhao 80 86201711045 liu 69 75201724397 TomHanks 85 90201700925 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 onceclass 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_Hstudent.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_Hcomplex.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_Hcomplex.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;}