普通算法题不太涉及的C++知识点(四):继承,多态

1. 继承:

1.1 继承的基本语法:

/*
//不使用继承:
class java{
public:
	void header(){
		cout << 1 << endl;
	}	
	void footer(){
		cout << 2 << endl;
	}
	void left(){
		cout << 3 << endl;
	}
	void content(){
		cout << 4 << endl;
	}
};

class python{
public:
	void header(){
		cout << 1 << endl;
	}	
	void footer(){
		cout << 2 << endl;
	}
	void left(){
		cout << 3 << endl;
	}
	void content(){
		cout << 4 << endl;
	}
};
*/

//使用继承:减少重复的代码
//语法: class 子类 : 继承方法 父类
class base{
public:
	void header(){
		cout << 1 << endl;
	}
	void footer(){
		cout << 2 << endl;
	}
	void left(){
		cout << 3 << endl;
	}
};

//java
class java : public base{
public:
	void content(){
		cout << 4 << endl;
	}
};

//python
class python : public base{
public:
	void content(){
		cout << 5 << endl;
	}
};

void test1(){
	java j;
	j.header();
	j.footer();
	j.left();
	j.content();
}

int main(){
	test1();
	return 0;
}

1.2 继承方式:

一共三种:公共继承,保护继承,私有继承。

\父类成员类型publicprotectedprivate
子类继承方法\\\\
public\publicprotected不可访问
protected\protectedprotected不可访问
private\privateprivate不可访问

1.3 继承中的对象模型:

从父类继承过来的成员,哪些属于子类对象?

class base{
public:
	int m_a;
protected:
	int m_b;
private:  //仍会被子类继承
	int m_c;
};

class son : public base{
public:
	int m_d;
};


void test1(){
	cout << sizeof(son) << endl;  //输出16
	//因为在父类中所有非静态成员属性都会被子类继承
	//父类中的私有成员只是被编译器隐藏了
}

int main(){
	test1();
	return 0;
}

1.4 继承中构造和析构顺序:

父类先构造,子类后构造;子类先析构,父类后析构。

1.5 继承的同名成员处理方式:

访问子类同名成员,直接访问;访问父类同名成员,需要加作用域。

class base{
public:
	base(){
		m_a = 100;
	}

	void func(){
		cout << 1 << endl;
	}
	int m_a;
};

class son : public base{
public:
	son(){
		m_a = 200;
	}

	void func(){
		cout << 2 << endl;
	}
	int m_a;
};

//同名成员属性
void test1(){
	son s1;
	cout << s1.m_a << endl;  //输出200
	cout << s1.base::m_a << endl;  //输出100
}

//同名成员函数
void test2(){
	son s2;
	s2.func();  //输出2
	s2.base::func();  //输出1
}

int main(){
	test1();
	test2();
	return 0;
}

1.6 继承的静态同名成员处理方式:

和非静态一样。访问子类同名成员,直接访问;访问父类同名成员,需要加作用域。

1.7 多继承语法:

class son : public base1, public base2{

};

1.8 菱形继承:

两个派生类继承同一个基类,又有某个类同时继承这两个派生类。

class base{};

class base1 : virtual public base{};

class base2 : virtual public base{};

//使用虚继承解决菱形继承问题
class son : public base1, public base2{

};

2. 多态:

2.1 多态的基本语法:

静态多态:函数重载,运算符重载,复用函数名;
动态多态:派生类和虚函数实现运行时多态;

静态多态和动态多态的区别:
静态多态的函数地址早绑定——编译阶段确定函数地址;
动态多态的函数地址晚绑定——运行阶段确定函数地址。

class animal{
public:
	virtual void speak(){
		cout << 1 << endl;
	}	
};

class cat : public animal{
public:
	void speak(){
		cout << 2 << endl;
	}
}

//地址早绑定,所以调用的是animal的speak函数
void dospeak(animal &animal1){  //允许父子之间的类型转换
	animal1.speak();
}
//地址晚绑定,才可以调用cat的speak函数

void test(){
	cat cat1;
	dospeak(cat1);  //animai类的speak不加virtual输出1,加了输出2
}

int main(){
	test();
	return 0;
}

2.2 多态原理:(?)

class animal{
public:
	//虚函数  vfptr指向vftable(虚函数表)
	virtual void speak(){
		cout << 1 << endl;
	}	
};

2.3 多态案例一:计算器类

普通写法:如果想要拓展新的功能,需要修改源码。
但在开发中提倡开闭原则:对扩展开放,对修改关闭。

class calculator(){
public:
	int getresult(string oper){
		if(oper=="+"){
			return m_num1 + m_num2;
		}
		else if(oper=="-"){
			return m_num1 - m_num2;
		}
		else if(oper=="*"){
			return m_num1 * m_num2;
		}
	}

	int m_num1;
	int m_num2;
};

void test(){
	calculator c1;
	c1.m_num1 = 10;
	c1.m_num2 = 20;
	cout << c1.getresult("+") << endl;
	cout << c1.getresult("-") << endl;
	cout << c1.getresult("*") << endl;
}

int main(){
	test();
	return 0;
}

多态技术:

//实现计算器抽象类
class abstract_calculator{
public:
	virtual int getresult(){
		return 0;
	}

	int m_num1;
	int m_num2;
};

class add : public abstract_calculator{
public:
	int getresult(){
		return m_num1 + m_num2;
	}
};

class sub : public abstract_calculator{
public:
	int getresult(){
		return m_num1 - m_num2;
	}
};

class mul : public abstract_calculator{
public:
	int getresult(){
		return m_num1 * m_num2;
	}
};


void test(){
	abstract_calculator * abc = new add;
	abc->m_num1 = 10;
	abc->m_num2 = 20;
	cout << abc->getresult() << endl;
	delete(abc);

	abc = new sub;
	abc->m_num1 = 10;
	abc->m_num2 = 20;
	cout << abc->getresult() << endl;
	delete(abc);

}

int main(){
	test();
	return 0;
}

2.4 纯虚函数和抽象类:

在多态中,通常父类中的虚函数是毫无意义的,主要都是调用子类重写的内容,因此可以将虚函数改为纯虚函数。
含有纯虚函数的类称为抽象类。抽象类无法实例化对象,子类必须重写抽象类的纯虚函数。

class base{
public:
	//纯虚函数:
	virtual void func() = 0;
};

class son : public base{
public:
	virtual void func(){
		cout << 1 << endl;
	}
};

2.5 多态案例二:制作饮品

抽象类制作饮品基类,子类制作咖啡和茶叶。

class drinking{
public:
	virtual void boil() = 0;
	virtual void brew() = 0;
	virtual void pour() = 0;
	virtual void put() = 0;
	void make(){
		boil();
		brew();
		pour();
		put();
	}
};

class coffee : public drinking{
public:
	virtual void boil(){
		cout << 1.1 << endl;
	}
	virtual void brew(){
		cout << 1.2 << endl;
	}
	virtual void pour(){
		cout << 1.3 << endl;
	}
	virtual void put(){
		cout << 1.4 << endl;
	}
};

class tea : public drinking{
public:
	virtual void boil(){
		cout << 2.1 << endl;
	}
	virtual void brew(){
		cout << 2.2 << endl;
	}
	virtual void pour(){
		cout << 2.3 << endl;
	}
	virtual void put(){
		cout << 2.4 << endl;
	}
};

void makedrink(drinking *d){
	d->make();
	delete d;
}

void test(){
	makedrink(new coffee);
}

int main(){
	test();
	return 0;
}

2.6 虚析构和纯虚析构:

多态使用时,如果子类有属性开辟到堆区,那么父类指针在释放时无法调用到子类的析构代码。
解决方法:将父类中的析构函数改为虚析构或纯虚析构。

class animal{
public:
	//虚析构
	virtual ~animal(){
		
	}
	//纯虚析构
	//virtual ~animal() = 0;  
	virtual void speak() = 0;
};
//纯虚析构
//animal::~animal(){
//	cout << 1 << endl;
//}


class cat : public animal{
public:
	cat(string name){
		m_name = new string(name);
	}
	~cat(){
		if(m_name!=NULL){
			delete m_name;
			m_name = NULL;
		}
	}

	virtual void speak(){
		cout << 1 << endl;
	}

	string *m_name;
};

void test(){
	animal *a = new cat("Tom");
	a->speak();
	delete a;   //直接delete父类指针,不会调用子类的析构函数,如果有使用过new,会发生内存泄漏。
	//将父类析构函数改为虚析构就可以解决此问题。
}

int main(){
	test();
	return 0;
}

2.7 多态案例三:电脑组装

电脑主要组成部件为CPU,显卡,内存条。

#include <iostream>

using namespace std;

class cpu{
public:
	virtual void calculate() = 0;
};
class videocard{
public:
	virtual void display() = 0;
};
class memory{
public:
	virtual void storage() = 0;
};

class computer{
public:
	computer(cpu *c, videocard *vc, memory *mem){
		m_c = c;
		m_vc = vc;
		m_mem = mem;
	}
	~computer(){
		if(m_c!=NULL){
			delete m_c;
			m_c = NULL;
		}
		if(m_vc!=NULL){
			delete m_vc;
			m_vc = NULL;
		}
		if(m_mem!=NULL){
			delete m_mem;
			m_mem = NULL;
		}
	}

	void work(){
		m_c->calculate();
		m_vc->display();
		m_mem->storage();
	}

private:
	cpu *m_c;
	videocard *m_vc;
	memory *m_mem;
};

class intelcpu : public cpu{
public:
	virtual void calculate(){
		cout << 1 << endl;
	}
};
class intelvc : public videocard{
public:
	virtual void display(){
		cout << 2 << endl;
	}
};
class intelmem : public memory{
public:
	virtual void storage(){
		cout << 3 << endl;
	}
};

void test(){
	cpu *c1 = new intelcpu;
	videocard * vc1 = new intelvc;
	memory *mem1 = new intelmem;

	computer *com1 = new computer(c1, vc1, mem1);
	com1->work();
	delete com1;
}

int main(){
	test();
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值