学习C++(十)

这篇博客探讨了C++中的继承概念,并通过实际案例展示了动态多态的运用。同时,介绍了策略者和工厂设计模式在实现加减乘除及动物表演场景中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

继承的案例

#include <iostream>
using namespace std;
/*
定义一个人员类Person,包含数据成员:姓名、ID。
在此基础上派生出学生类Student(增加成绩属性)和老师类Teacher(增加教龄)。
主函数测试实现对学生和老师信息的输入输出。
*/
class Person{
private:
	string name;
	int id;
public:
    //构造函数
	Person(const string& name, int id);
    
    //get set
	const string& getName() const { return this->name; }
	int getId() const { return this->id; }

	void setName(const string& name) { this->name = name; }
	void setId(int id) { this->id = id; }

	//虚方法
	virtual void display() const{}//输出
	virtual void input() {}//输入
};

class Student : public Person{
private:
	int score;
public:
	Student(const string& name, int id, int score);

	void display() const;
	void input();
};

class Teacher : public Person{
private:
	int teacherYear;
public:
	Teacher(const string& name, int id, int teacherYear);

	void display() const;
	void input();
};

Person::Person(const string& name, int id)
	:name(name),
	id(id)
{

}

Student::Student(const string& name, int id, int score)
	:Person(name, id),
	score(score)
{

}

Teacher::Teacher(const string& name, int id, int teacherYear)
	:Person(name, id),
	teacherYear(teacherYear)
{

}

void Student::display() const
{
	cout << "这是学生:";
	cout << this->getId() << "\t" << this->getName()
		<< "\t" << this->score << endl;
}

void Student::input()
{
	string name;
	int id = 0;
	cin >> name >> id >>this->score;
	this->setName(name);
	this->setId(id);
}

void Teacher::display() const
{
	cout << "这是老师:";
	cout << this->getId() << "\t" << this->getName()
		<< "\t" << this->teacherYear << endl;
}

void Teacher::input()
{
	string name;
	int id = 0;
	cin >> name >> id >> teacherYear;
	this->setName(name);
	this->setId(id);
}

int main()
{
	Student tom("yyy", 101, 89);
	Teacher willian("kkk", 102, 3);

	Person* p = &tom;//用指针来测试对象

	p->display();
	cout << "请输入学生信息(name,id,score):";
	p->input();
	p->display();

	p = &willian;
	p->display();
	cout << "请输入老师信息(name,id,teacherYear):";
	p->input();
	p->display();

	return 0;
}

在这里插入图片描述

动态多态的案例

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

using namespace std;

/*
	定义一个Person类,包含属性:姓名,年龄,性别;写好相关的方法,能够构造的时候初始化或者后续修改属性值 
	定义一个Runnable抽象类,包含纯虚函数run。 
	定义一个Athlete类分别继承Person类和Runnable类,重写run函数(能在调用run时打印 Athlete的姓名和跑步时的速度(生成随机数即可))。 
	在主函数中创建一个Athlete对象, 
	尝试:使用Person指针指向该对象然后调用run函数 
	尝试:使用Runnable指针指向该对象然后调用run函数。
	哪些是可行的,哪些是不可行的?为什么?原因在注释中用明确的文字进行说明。
*/

class Person{
private:
	string	name;
	int 	year;
	bool 	isMale;
public:
	Person(const string& name, int year, bool isMale);

	//get set 
	void setName(const string& name) { this->name = name; }
	void setYear(int year) { this->year = year; }
	void setIsMale(int isMale) { this->isMale = isMale; }

	const string& getName() const { return this->name; }
	int getYear() const { return this->year; }
	bool getIsMale() const { return this->isMale; }
};

//抽象类:一个类中存在纯虚函数这个类就是抽象类
//抽象类不能实例化对象  如果派生类没有重写基类的纯虚函数,那么派生类也是抽象类
class Runnable{
public:
	virtual void run() = 0;			//纯虚函数(不需要定义)
};

class Athlete : public Person, public Runnable{
public:
	Athlete(const string& name, int year, bool isMale);
	void run();
};

Person::Person(const string& name, int year, bool isMale)
	:name(name),
	year(year),
	isMale(isMale)
{

}

Athlete::Athlete(const string& name, int year, bool isMale)
	:Person(name, year, isMale)
{
	srand(time(0));
}

void Athlete::run()
{
	cout << "name: " << this->getName() 
			<< ", year: " << this->getYear() 
			<< ", isMale: " << this->getIsMale()
			<< ", speed: " << rand() % 10 + 1 << endl;
}

int main(void)
{	
	Athlete athlete("willian", 30, true);
	Person* p = &athlete;
	//p->run();			基类指针只能访问基类的区间,基类没有定义run方法

	Runnable* rp = &athlete;
	rp->run();			//动态多态的实现过程

	//Runnable r;		抽象类不能创建对象

	return 0;
}

在这里插入图片描述

策略者设计模式

//Figure.h
#ifndef FIGURE_H_
#define FIGURE_H_

#include <iostream>
using namespace std;

/*
定义点类(二维,即包含x,y坐标) Point

定义一个图形类Figure:包含方法画图(onDraw)

定义一个三角形继承于图形类,
属性:三个点
方法:设置点,获取点等相关方法以及重写的画图方法
注:画图方法中要求打印出 画出的是一个什么图形和各个点坐标

定义一个圆形类,和三角形要求一致

定义一个画家类Painter
void draw(Figure* f);
方法:画画:可以画出一个图形
测试画家画画,画一个三角形,一个圆形

Point 表示点
Figure 图形类  抽象类
Triangle 三角形类
Circle	圆形类
Painter	画家类

Point 工具类

图形类---->三角形(策略1)	
      ---->圆形(策略2)

画家  策略的调度者
*/

/*工具类*/
class Point{
friend ostream& operator << (ostream& out, const Point& rhs);//友元
private:
	int 	x;
	int 	y;
public:
	Point(int x, int y);

	//set get...
};

/*图形类*/
class Figure{
public:
	virtual void onDraw() = 0;//纯虚函数
};

/*三角形类(策略1)*/
class Triangle : public Figure{
private:
	Point p1;
	Point p2;
	Point p3;
public:
	Triangle(const Point& p1, const Point& p2, const Point& p3);

	void onDraw();
};

/*圆形类(策略2)*/
class Circle : public Figure{
private:
	Point 	center;
	int 	radius;
public:
	Circle(const Point& center, int radius);

	void onDraw();
};

#endif
//Figure.cpp
#include "Figure.h"

Point::Point(int x, int y)
	:x(x),
	y(y)
{

}

//工具类的友元,用于输出点
ostream& operator << (ostream& out, const Point& rhs)
{
	out << "(" << rhs.x << ", " << rhs.y << ")";
	return out;
}

Triangle::Triangle(const Point& p1, const Point& p2, const Point& p3)
	:p1(p1),
	p2(p2),
	p3(p3)
{

}

void Triangle::onDraw()
{
	cout << "三角形: " << endl;
	cout << p1 << ", " << p2 << ", " << p3 << endl;
}

Circle::Circle(const Point& center, int radius)
	:center(center),
	radius(radius)
{

}

void Circle::onDraw()
{
	cout << "圆形: " << endl;
	cout << "圆心: " << this->center 
			<< ", 半径: " << this->radius << endl;
}
//main.cpp
/*
	继承:is-a
	组合和聚合: has-a
		组合		强的拥有关系	部分和整体的生命周期保持一致
		聚合		弱的拥有关系	部分和整体可以独立存在
	依赖和关联: 知道
		依赖	一个类需要用到另一个类来完成某种行为时	
		关联	一个类需要知道另一类才能完成多种行为
	接口:	抽象方法(多态)
*/
#include "Figure.h"

/*画家类*/
class Painter{
private:
	Figure* f;				//具体策略
public:
	Painter(Figure* f) :f(f) { }
	void draw() { f->onDraw(); }			//调用策略
	void modify(Figure* f) { this->f = f; }	//修改策略
};

int main(void)
{
	Triangle t(Point(2,3), Point(5,9), Point(4,5));
	Circle c(Point(3,3), 10);

	Painter painter(&t);
	painter.draw();			//绘制三角形
	
	painter.modify(&c);
	painter.draw();			//绘制圆形


	return 0;
}

在这里插入图片描述

工厂设计模式

加减乘除

在这里插入图片描述

//operation.h
#ifndef OPERATION_H_
#define OPERATION_H_

class Operation{
protected:
	double	numA;
	double	numB;
public:	
	void setNumberA(double numA) { this->numA = numA; }
	void setNumberB(double numB) { this->numB = numB; }
	virtual double getResult() const = 0;			//纯虚方法
};

class Add : public Operation{
public:
	double getResult() const { return this->numA + this->numB; }
};

class Mul : public Operation{
public:
	double getResult() const { return this->numA * this->numB; }
};

class Div : public Operation{
public:
	double getResult() const { return this->numA / this->numB; }	
};

class Sub : public Operation{
public:
    double getResult() const { return this->numA - this->numB; }
};

#endif
//main.cpp
#include "operation.h"
#include <iostream>
using namespace std;

//简单工厂			//单个产品
//工厂方法			//单个产品
//抽象工厂			//批量产品的创建

class Factory{
public:
	//sign  运算符  Operation* 运算对象   根据运算符创建不同的产品对象
	Operation* createOper(char sign)
	{
		Operation* op = 0;
		switch(sign){
			case '+':
				op = new Add();
				break;
			case '-':
				op = new Sub();
				break;
			case '*':
				op = new Mul();
				break;
			case '/':
				op = new Div();
				break;
			default:
				break;
		}
		return op;
	}

};

//开放封闭原则: 对拓展开放  对修改关闭
int main(void)
{	
	double numA = 0.0, numB = 0.0;
	char sign = '\0';
	cout << "请输入运算公式:";
	cin >> numA >> sign >> numB;
	
	//创建工厂
	Factory f;
	//创建产品
	Operation* p = f.createOper(sign);
	if(0 == p){
		return 0;
	}

	//运算
	p->setNumberA(numA);
	p->setNumberB(numB);
	double result = p->getResult();

	cout << numA << " " << sign << " " << numB << " = " << result << endl;

	return 0;
}

在这里插入图片描述

动物表演

在这里插入图片描述

//animal.h
#ifndef ANIMAL_H_
#define ANIMAL_H_
#include <iostream>
using namespace std;

class Animal{
public:
	virtual void display() const = 0;
};

class Lion : public Animal{
private:
	//...
public:
	void display() const { cout << "钻火圈" << endl; }
};

class Elephant : public Animal{
private:
	//...
public:
	void display() const { cout << "喷水" << endl; }
};

class Dolphin : public Animal{
private:
	//...
public:
	void display() const { cout << "转球" << endl; }
};

#endif
//main.cpp
#include "animal.h"
#include <cstring>

//训兽员
class Trainter{
private:
	enum {SIZE = 20 };
	Animal* animals[SIZE];
	int 	count;			//实际动物的个数
public:
	Trainter()
		:count(0)
	{
		memset(animals, 0, sizeof(animals));
	}
	//添加动物
	int insertAnimal(Animal* animal);			//注册观察者
	//移除动物
	int removeAnimal(Animal* animal);			//移除观察者

	//让所有动物表演
	void displayAll() const;					//通知观察者
};

int Trainter::insertAnimal(Animal* animal)
{
	if(count >= SIZE){
		return -1;		//失败
	}
	//添加
	animals[count++] = animal;
	return 0;
}

int Trainter::removeAnimal(Animal* animal)
{
	if(count == 0){
		return -1;
	}

	//移除
	for(int i = 0; i < count; i++){
		if(animal == animals[i]){
			//删除
			int j = i;
			for(; j < count - 1; j++){
				animals[j] = animals[j + 1];
			}
			count--;
			return 0;
		}
	}
	return -1;
}

void Trainter::displayAll() const
{
	for(int i = 0; i < count; i++){
		animals[i]->display();
	}
}

int main(void)
{
	Lion lion;
	Elephant elephant;
	Dolphin dolphin;

	Trainter trainter;
	trainter.insertAnimal(&lion);
	trainter.insertAnimal(&elephant);
	trainter.insertAnimal(&dolphin);
    
	trainter.displayAll();

	//移除狮子
    cout << "*****移除狮子*****" << endl;
	trainter.removeAnimal(&lion);

	trainter.displayAll();

	return 0;
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值