【c++思维导图与代码示例】06 类的继承与派生

【c++思维导图与代码示例】06 类的继承与派生

思维导图:

在这里插入图片描述

代码示例:

  • 示例1:
/*************************************************
*
**Description: 类的公有继承举例(点类---》派生矩形类)
**              
** Author:慕灵阁-wupke
** Time:2021-12-15
** Versions :6-1.cpp
** 
*
***************************************************/
#include <iostream>
#include <cmath>
using namespace std;

class Point {	//基类Point类的定义
public:	//公有函数成员
	void initPoint(float x = 0, float y = 0) { this->x = x; this->y = y;}
	void move(float offX, float offY) { x += offX; y += offY; }
	float getX() const { return x; }
	float getY() const { return y; }
private:	//私有数据成员
	float x, y;
};

class Rectangle: public Point {	//派生类定义部分
public:	//新增公有函数成员
	void initRectangle(float x, float y, float w, float h) {
		initPoint(x, y); //调用基类公有成员函数
		this->w = w;
		this->h = h;
	}
	float getH() const { return h; }
	float getW() const { return w; }
private:	//新增私有数据成员
	float w, h;
};

int main() {
	Rectangle rect;	//定义Rectangle类的对象
	rect.initRectangle(2, 3, 20, 10);	//设置矩形的数据
	rect.move(3,2);	//移动矩形位置
	cout << "The data of rect(x,y,w,h): " << endl;
	cout << rect.getX() <<", "	//输出矩形的特征参数
		<< rect.getY() << ", "
		<< rect.getW() << ", "
		<< rect.getH() << endl;
    system("pause");
	return 0;
}

  • 示例2:
/*************************************************
*
**Description: 类的私有继承举例(点类---》派生矩形类)
**              
** Author:慕灵阁-wupke
** Time:2021-12-15
** Versions :6-2.cpp
** 
*
***************************************************/
#include <iostream>
#include <cmath>
using namespace std;

class Point {	//基类Point类的定义
public:	//公有函数成员
	void initPoint(float x = 0, float y = 0) { this->x = x; this->y = y;}
	void move(float offX, float offY) { x += offX; y += offY; }
	float getX() const { return x; }
	float getY() const { return y; }
private:	//私有数据成员
	float x, y;
};

class Rectangle: private Point {	//派生类定义部分(私有继承)
public:	//新增公有函数成员
	void initRectangle(float x, float y, float w, float h) {
		initPoint(x, y); //调用基类公有成员函数
		this->w = w;
		this->h = h;
	}
	void move(float offX, float offY) { Point::move(offX, offY); }
	float getX() const { return Point::getX(); }
	float getY() const { return Point::getY(); }
	float getH() const { return h; }
	float getW() const { return w; }
private:	//新增私有数据成员
	float w, h;
};


int main() {
	Rectangle rect;	//定义Rectangle类的对象
	rect.initRectangle(2, 3, 20, 10);	//设置矩形的数据
	rect.move(3,2);	//移动矩形位置
	cout << "The data of rect(x,y,w,h): " << endl;
	cout << rect.getX() <<", "	//输出矩形的特征参数
		<< rect.getY() << ", "
		<< rect.getW() << ", "
		<< rect.getH() << endl;
    system("pause");
	return 0;
}



  • 示例3:
/*************************************************
*
**Description: 类的保护继承举例
**              
** Author:慕灵阁-wupke
** Time:2021-12-15
** Versions :6-3.cpp
** 
*
***************************************************/

/*    错误访问     */
class A {
protected:
    int x;
};

int main() {
    A a;
    a.x = 5;//错误形式
}

/*    正确访问     */
class A {
protected:
    int x;
};
class B: public A{
public:
    void function();
};
void B:function() {
    x = 5;   //正确
}

  • 示例4:
/*************************************************
*
**Description: 类的多继承举例
**              
** Author:慕灵阁-wupke
** Time:2021-12-15
** Versions :6-4.cpp
** 
*
***************************************************/
#include <iostream>
#include <cmath>
using namespace std;

class A {
public:
    void setA(int);
    void showA() const;
private:
    int a;
};
class B {
public:
    void setB(int);
    void showB() const;
private:
    int b;
};
class C : public A, private B { 
public:
    void setC(int, int, int);
    void showC() const;
private:
    int c;
};


void  A::setA(int x) {
    a=x; 
}
void B::setB(int x) {
    b=x; 
}
void C::setC(int x, int y, int z) {
    //派生类成员直接访问基类的公有成员
    setA(x); 
    setB(y); 
    c = z;
}
//其他函数实现略
int main() { 
    C obj;
    obj.setA(5);
    obj.showA();
    obj.setC(6,7,9);
    obj.showC();
// obj.setB(6);  错误
// obj.showB(); 错误
    system("pause");
    return 0;
}

  • 示例5:
/*************************************************
*
**Description: 类型转换规则举例
**              
** Author:慕灵阁-wupke
** Time:2021-12-15
** Versions :6-5.cpp
** 
*
***************************************************/
#include <iostream>
using namespace std;

class Base1 { //基类Base1定义
public:
	void display() const { cout << "Base1::display()" << endl; }
};

class Base2: public Base1 { //公有派生类Base2声明定义
public:
	void display() const { cout << "Base2::display()" << endl; }
};

class Derived: public Base2 { //公有派生类Derived声明定义
public:
	void display() const { cout << "Derived::display()" << endl; }
};

void fun(Base1 *ptr) { //参数为指向基类对象的指针
	ptr->display();	//"对象指针->成员名"
}

int main() {	//主函数
	Base1 base1;	//声明Base1类对象
	Base2 base2;	//声明Base2类对象
	Derived derived;	//声明Derived类对象

	fun(&base1);	//用Base1对象的指针调用fun函数
	fun(&base2);	//用Base2对象的指针调用fun函数
	fun(&derived);	//用Derived对象的指针调用fun函数
    system("pause");
	return 0;
}


  • 示例6:
/*************************************************
*
**Description: 派生类的构造函数举例
**              
** Author:慕灵阁-wupke
** Time:2021-12-15
** Versions :6-6.cpp
** 
*
***************************************************/

#include <iostream>
using namespace std;

class Base1 {	//基类Base1,构造函数有参数
public:
	Base1(int i) { cout << "Constructing Base1 " << i << endl; }
};

class Base2 {	//基类Base2,构造函数有参数
public:
	Base2(int j) { cout << "Constructing Base2 " << j << endl; }
};

class Base3 {	//基类Base3,构造函数无参数
public:
	Base3() { cout << "Constructing Base3 *" << endl; }
};

class Derived: public Base2, public Base1, public Base3 {
//派生新类Derived,注意基类名的顺序
public:	//派生类的公有成员
	Derived(int a, int b, int c, int d): Base1(a), member2(d), member1(c), Base2(b) { }
	//注意基类名的个数与顺序,注意成员对象名的个数与顺序
private:	//派生类的私有成员对象
	Base1 member1;
	Base2 member2;
	Base3 member3;
};

int main() {
	Derived obj(1, 2, 3, 4);
    system("pause");
	return 0;
}



  • 示例7:
/*************************************************
*
**Description: 派生类的析构函数举例
**              
** Author:慕灵阁-wupke
** Time:2021-12-15
** Versions :6-7.cpp
** 
*
***************************************************/
#include <iostream>
using namespace std;

class Base1 {	//基类Base1,构造函数有参数
public:
	Base1(int i) { cout << "Constructing Base1 " << i << endl; }
	~Base1() { cout << "Destructing Base1" << endl; }
};

class Base2 {	//基类Base2,构造函数有参数
public:
	Base2(int j) { cout << "Constructing Base2 " << j << endl; }
	~Base2() { cout << "Destructing Base2" << endl; }
};

class Base3 {	//基类Base3,构造函数无参数
public:
	Base3() { cout << "Constructing Base3 *" << endl; }
	~Base3() { cout << "Destructing Base3" << endl; }
};

class Derived: public Base2, public Base1, public Base3 {
//派生新类Derived,注意基类名的顺序
public:	//派生类的公有成员
	Derived(int a, int b, int c, int d): Base1(a), member2(d), member1(c), Base2(b) { }
	//注意基类名的个数与顺序,注意成员对象名的个数与顺序
private:	//派生类的私有成员对象
	Base1 member1;
	Base2 member2;
	Base3 member3;
};

int main() {
	Derived obj(1, 2, 3, 4);
    // system("pause");  // 使用vscode,代码中添加此句,看不到析构函数的调用显示
	return 0;
}

  • 示例8:

/*************************************************
*
**Description:  多继承同名隐藏举例:
 	当派生类与基类中有相同成员时:若未特别限定,则通过派生类对象使用的是派生类中的同名成员。
如要通过派生类对象访问基类中被隐藏的同名成员,应使用基类名和作用域操作符(::)来限定。  
**              
** Author:慕灵阁-wupke
** Time:2021-12-15
** Versions :6-8.cpp
** 
*
***************************************************/

#include <iostream>
using namespace std;

class Base1 {	//定义基类Base1
public:
	int var;
	void fun() { cout << "Member of Base1" << endl; }
};

class Base2 {	//定义基类Base2
public:
	int var;
	void fun() { cout << "Member of Base2" << endl; }
};

class Derived: public Base1, public Base2 {	//定义派生类Derived ,公有继承自 Base1, Base2
public:
	int var;	//同名数据成员
	void fun() { cout << "Member of Derived" << endl; }	//同名函数成员
};

int main() {
	Derived d;
	Derived *p = &d;

	d.var = 1;	//对象名.成员名标识
	d.fun();	//访问D1类成员
	
	d.Base1::var = 2;	//作用域分辨符标识
	d.Base1::fun();	//访问Base1基类成员
	
	p->Base2::var = 3;	//作用域分辨符标识
	p->Base2::fun();	//访问Base2基类成员

	// system("pause");
	return 0;
}

  • 示例9:
/*************************************************
*
**Description:多继承时的二义性问题举例
**             
** Author:慕灵阁-wupke
** Time:2021-12-15
** Versions :6-9.cpp
** 
*
***************************************************/

class A {
public:
    void  f();
};
class B {
public:
    void f();
    void g()
};
class C: public A, piblic B {
public:
    void g();
    void h();
};
/*
如果定义:C  c1;
则 c1.f() 具有二义性
而 c1.g() 无二义性(同名隐藏)


解决方法一:可以使用类名限定
c1.A::f()    或   c1.B::f()  

解决方法二:同名隐藏机制
在类 C 中,声明一个同名函数 f(),  f() 再根据需要调用 A::f() 或 B::f() 

*/

  • 示例10:
/*************************************************
*
**Description:多继承时的冗余问题举例,virtual 虚基类的使用
**             
** Author:慕灵阁-wupke
** Time:2021-12-15
** Versions :6-10.cpp
** 
*
***************************************************/

#include <iostream>
using namespace std;

class Base0 {	//定义基类Base0
public:
	int var0;
	void fun0() { cout << "Member of Base0" << endl; }
};

class Base1: public Base0 {	//定义派生类Base1
public:	//新增外部接口
	int var1;
};

class Base2: public Base0 {	//定义派生类Base2
public:	//新增外部接口
	int var2;
};

class Derived: public Base1, public Base2 {	//定义派生类Derived
public:	//新增外部接口
	int var;
	void fun() { cout << "Member of Derived" << endl; }
};

int main() {	//程序主函数
	Derived d;			//定义Derived类对象d
	d.Base1::var0 = 2;	//使用直接基类
	d.Base1::fun0();
	d.Base2::var0 = 3;	//使用直接基类
	d.Base2::fun0();
	return 0;
}


/* Derived 类中有从base1中继承来的base0类,也有从base2中继承来的base0类
(分别可能继承了相同的内容,产生了冗余,占据多的内存)*/

// 使用关键字:virtual 虚基类避免此类问题
// 这样,在Derived 类中就不会有从base1与base2中继承来的base0类中相同的内容

#include <iostream>
using namespace std;

class Base0 {	//定义基类Base0
public:
	int var0;
	void fun0() { cout << "Member of Base0" << endl; }
};

class Base1: virtual public Base0 {	//定义派生类Base1
public:	//新增外部接口
	int var1;
};

class Base2: virtual public Base0 {	//定义派生类Base2
public:	//新增外部接口
	int var2;
};

class Derived: public Base1, public Base2 {	//定义派生类Derived
public:	//新增外部接口
	int var;
	void fun() { cout << "Member of Derived" << endl; }
};

int main() {	//程序主函数
	Derived d;	//定义Derived类对象d
	d.var0 = 2;	//直接访问虚基类的数据成员
	d.fun0();	//直接访问虚基类的函数成员
	return 0;
}

  • 示例11:
/*************************************************
*
**Description:有虚基类时的构造函数举例

	• 建立对象时所指定的类称为最远派生类。
	• 虚基类的成员是由最远派生类的构造函数通过调用虚基类的构造函数进行初始化的。
	• 在整个继承结构中,直接或间接继承虚基类的所有派生类,都必须在构造函数的成员初始化表中为虚基类的构造函数列出参数。如果未列出,则表示调用该虚基类的默认构造函数。
	• 在建立对象时,只有最远派生类的构造函数调用虚基类的构造函数,其他类对虚基类构造函数的调用被忽略。
**             
** Author:慕灵阁-wupke
** Time:2021-12-15
** Versions :6-11.cpp
** 
*
***************************************************/
#include <iostream>
using namespace std;
class Base0 {    
public:
    Base0(int var) : var0(var) { }
    int var0;
    void fun0() { cout << "Member of Base0" << endl; }
};
class Base1: virtual public Base0 {
public: 
    Base1(int var) : Base0(var) { }
    int var1;
};
class Base2: virtual public Base0 { 
public:
    Base2(int var) : Base0(var) { }
    int var2;
};
class Derived: public Base1, public Base2 {
public:
    Derived(int var) : Base0(var), Base1(var), Base2(var) 
   { }
    int var;
    void fun() 
   { cout << "Member of Derived" << endl; }
};
int main() {    //程序主函数
    Derived d(1);
    d.var0 = 2; //直接访问虚基类的数据成员
    d.fun0();   //直接访问虚基类的函数成员
    return 0;
}

  • 示例12:

/*************************************************
*
**Description: 类的综合示例   ————  银行账户管理
**              详细代码共分6个文件

** Author:慕灵阁-wupke
** Time:2021-12-15
** Versions :6-12.cpp
** 
*
***************************************************/
#include <iostream>
#include "D:\Software\VSCode\C++\unit-7\7-10\account.h"
#include "D:\Software\VSCode\C++\account.cpp"
#include "D:\Software\VSCode\C++\date.cpp"
#include "D:\Software\VSCode\C++\accumulator.h"
#include "D:\Software\VSCode\C++\date.h"
using namespace std;

int main() {
	Date date(2008, 11, 1);	//起始日期
	//建立几个账户
	SavingsAccount sa1(date, "S3755217", 0.015);
	SavingsAccount sa2(date, "02342342", 0.015);
	CreditAccount ca(date, "C5392394", 10000, 0.0005, 50);
	//11月份的几笔账目
	sa1.deposit(Date(2008, 11, 5), 5000, "salary");
	ca.withdraw(Date(2008, 11, 15), 2000, "buy a cell");
	sa2.deposit(Date(2008, 11, 25), 10000, "sell stock 0323");
	//结算信用卡
	ca.settle(Date(2008, 12, 1));
	//12月份的几笔账目
	ca.deposit(Date(2008, 12, 1), 2016, "repay the credit");
	sa1.deposit(Date(2008, 12, 5), 5500, "salary");
	//结算所有账户
	sa1.settle(Date(2009, 1, 1));
	sa2.settle(Date(2009, 1, 1));
	ca.settle(Date(2009, 1, 1));
	//输出各个账户信息
	cout << endl;
	sa1.show(); cout << endl;
	sa2.show(); cout << endl;
	ca.show(); cout << endl;
	cout << "Total: " << Account::getTotal() << endl;
	
	system("pause");
	return 0;
}




//account.h
#ifndef __ACCOUNT_H__
#define __ACCOUNT_H__
#include "date.h"
#include "accumulator.h"
#include <string>

class Account { //账户类
private:
	std::string id;	//帐号
	double balance;	//余额
	static double total; //所有账户的总金额
protected:
	//供派生类调用的构造函数,id为账户
	Account(const Date &date, const std::string &id);
	//记录一笔帐,date为日期,amount为金额,desc为说明
	void record(const Date &date, double amount, const std::string &desc);
	//报告错误信息
	void error(const std::string &msg) const;
public:
	const std::string &getId() const { return id; }
	double getBalance() const { return balance; }
	static double getTotal() { return total; }
	//显示账户信息
	void show() const;
};

class SavingsAccount : public Account { //储蓄账户类
private:
	Accumulator acc;	//辅助计算利息的累加器
	double rate;		//存款的年利率
public:
	//构造函数
	SavingsAccount(const Date &date, const std::string &id, double rate);
	double getRate() const { return rate; }
	//存入现金
	void deposit(const Date &date, double amount, const std::string &desc);
	//取出现金
	void withdraw(const Date &date, double amount, const std::string &desc);
	//结算利息,每年1月1日调用一次该函数
	void settle(const Date &date);
};

class CreditAccount : public Account { //信用账户类
private:
	Accumulator acc;	//辅助计算利息的累加器
	double credit;		//信用额度
	double rate;		//欠款的日利率
	double fee;			//信用卡年费

	double getDebt() const {	//获得欠款额
		double balance = getBalance();
		return (balance < 0 ? balance : 0);
	}
public:
	//构造函数
	CreditAccount(const Date &date, const std::string &id, double credit, double rate, double fee);
	double getCredit() const { return credit; }
	double getRate() const { return rate; }
	double getFee() const { return fee; }
	double getAvailableCredit() const {	//获得可用信用
		if (getBalance() < 0) 
			return credit + getBalance();
		else
			return credit;
	}
	//存入现金
	void deposit(const Date &date, double amount, const std::string &desc);
	//取出现金
	void withdraw(const Date &date, double amount, const std::string &desc);
	//结算利息和年费,每月1日调用一次该函数
	void settle(const Date &date);

	void show() const;
};

#endif //__ACCOUNT_H__




//account.cpp
#include "account.h"
#include <cmath>
#include <iostream>
using namespace std;

double Account::total = 0;

//Account类的实现
Account::Account(const Date &date, const string &id)
	: id(id), balance(0) {
	date.show();
	cout << "\t#" << id << " created" << endl;
}

void Account::record(const Date &date, double amount, const string &desc) {
	amount = floor(amount * 100 + 0.5) / 100;	//保留小数点后两位
	balance += amount;
	total += amount;
	date.show();
	cout << "\t#" << id << "\t" << amount << "\t" << balance << "\t" << desc << endl;
}

void Account::show() const {
	cout << id << "\tBalance: " << balance;
}

void Account::error(const string &msg) const {
	cout << "Error(#" << id << "): " << msg << endl;
}

//SavingsAccount类相关成员函数的实现
SavingsAccount::SavingsAccount(const Date &date, const string &id, double rate)
	: Account(date, id), rate(rate), acc(date, 0) { }

void SavingsAccount::deposit(const Date &date, double amount, const string &desc) {
	record(date, amount, desc);
	acc.change(date, getBalance());
}

void SavingsAccount::withdraw(const Date &date, double amount, const string &desc) {
	if (amount > getBalance()) {
		error("not enough money");
	} else {
		record(date, -amount, desc);
		acc.change(date, getBalance());
	}
}

void SavingsAccount::settle(const Date &date) {
	double interest = acc.getSum(date) * rate	//计算年息
		/ date.distance(Date(date.getYear() - 1, 1, 1));
	if (interest != 0)
		record(date, interest, "interest");
	acc.reset(date, getBalance());
}

//CreditAccount类相关成员函数的实现
CreditAccount::CreditAccount(const Date& date, const string& id, double credit, double rate, double fee)
	: Account(date, id), credit(credit), rate(rate), fee(fee), acc(date, 0) { }

void CreditAccount::deposit(const Date &date, double amount, const string &desc) {
	record(date, amount, desc);
	acc.change(date, getDebt());
}

void CreditAccount::withdraw(const Date &date, double amount, const string &desc) {
	if (amount - getBalance() > credit) {
		error("not enough credit");
	} else {
		record(date, -amount, desc);
		acc.change(date, getDebt());
	}
}

void CreditAccount::settle(const Date &date) {
	double interest = acc.getSum(date) * rate;
	if (interest != 0)
		record(date, interest, "interest");
	if (date.getMonth() == 1)
		record(date, -fee, "annual fee");
	acc.reset(date, getDebt());
}

void CreditAccount::show() const {
	Account::show();
	cout << "\tAvailable credit:" << getAvailableCredit();
}






//accumulator.h
#ifndef __ACCUMULATOR_H__
#define __ACCUMULATOR_H__
#include "date.h"

class Accumulator {	//将某个数值按日累加
private:
	Date lastDate;	//上次变更数值的时期
	double value;	//数值的当前值
	double sum;		//数值按日累加之和
public:
	//构造函数,date为开始累加的日期,value为初始值
	Accumulator(const Date &date, double value)
		: lastDate(date), value(value), sum(0) { }

	//获得到日期date的累加结果
	double getSum(const Date &date) const {
		return sum + value * date.distance(lastDate);
	}

	//在date将数值变更为value
	void change(const Date &date, double value) {
		sum = getSum(date);
		lastDate = date;
		this->value = value;
	}

	//初始化,将日期变为date,数值变为value,累加器清零
	void reset(const Date &date, double value) {
		lastDate = date;
		this->value = value;
		sum = 0;
	}
};

#endif //__ACCUMULATOR_H__






//date.h
#ifndef __DATE_H__
#define __DATE_H__

class Date {	//日期类
private:
	int year;		//年
	int month;		//月
	int day;		//日
	int totalDays;	//该日期是从公元元年1月1日开始的第几天

public:
	Date(int year, int month, int day);	//用年、月、日构造日期
	int getYear() const { return year; }
	int getMonth() const { return month; }
	int getDay() const { return day; }
	int getMaxDay() const;		//获得当月有多少天
	bool isLeapYear() const {	//判断当年是否为闰年
		return year % 4 == 0 && year % 100 != 0 || year % 400 == 0;
	}
	void show() const;			//输出当前日期
	//计算两个日期之间差多少天	
	int distance(const Date& date) const {
		return totalDays - date.totalDays;
	}
};

#endif //__DATE_H__







//date.cpp
#include "date.h"
#include <iostream>
#include <cstdlib>
using namespace std;

namespace {	//namespace使下面的定义只在当前文件中有效
	//存储平年中某个月1日之前有多少天,为便于getMaxDay函数的实现,该数组多出一项
	const int DAYS_BEFORE_MONTH[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
}

Date::Date(int year, int month, int day) : year(year), month(month), day(day) {
	if (day <= 0 || day > getMaxDay()) {
		cout << "Invalid date: ";
		show();
		cout << endl;
		exit(1);
	}
	int years = year - 1;
	totalDays = years * 365 + years / 4 - years / 100 + years / 400
		+ DAYS_BEFORE_MONTH[month - 1] + day;
	if (isLeapYear() && month > 2) totalDays++;
}

int Date::getMaxDay() const {
	if (isLeapYear() && month == 2)
		return 29;
	else
		return DAYS_BEFORE_MONTH[month]- DAYS_BEFORE_MONTH[month - 1];
}

void Date::show() const {
	cout << getYear() << "-" << getMonth() << "-" << getDay();
}



  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值