<6> 面向对象到底有什么(下)?

接着我们上次没有介绍完的内容,我们说OOP的三大特性,还有个特性是“多态”。乍一看,这个名字有点吓人。本篇博客将介绍“多态”是什么?为什么会用到“多态”这个特性?在哪里会用到?等这三个问题,来巩固自己对于面向对象的理解。

2.4 “多态”究竟是什么?(C++)

多态”从字面意思上来看是“多种形态”的意思,在我们的面向对象中,多态意味着基类的形态是可以多变的,通过多态可以将基类对象赋予子类的特性,对于不同的子类,使得基类产生不同的解释,执行不同的操作,生成不同的结果。在C++中,实现多态有虚函数、抽象类等技术。

2.5 “为什么”会用到多态的特性?

我们依然用之前的Person类作为样例,来进行剖析。请看下边的代码:

#include <iostream>
#include <vector>
#include <cmath>
#include <string>




//----------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------
// Person ( 基类 )


class Person {

public:
	Person(int age, char gender, std::string name)
		:_age(age),
		 _gender(gender),
		 _name(name)
	{}

	~Person();

public:
	int  _age;
	char _gender;
	std::string _name;

public:
	const int get_age() { return _age; }
	const char get_gender() { return _gender; }
	const std::string get_name() { return _name; }
	void set_age(const int &value);
	void set_gender(const char &value);
	void set_name(const std::string &value);
	void describe();
};


void Person::set_age(const int &value) {
	this->_age = value;
}

void Person::set_gender(const char &value) {
	this->_gender = value;
}

void Person::set_name(const std::string &value) {
	this->_name = value;
}

void Person::describe() {
	std::cout << "I am Person" << std::endl;
}

Person::~Person()
{
	//
}



//----------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------
// Student ( 派生类,继承自Person )

class Student :public Person {

public:
	Student(int age, char gender, std::string name,
			double *score,std::string ID,
			std::string major)
								:	Person(age,gender,name),
									_score(score),
									_studentID(ID),
									_major(major)
	{}

	~Student(){}

private:
	double *_score;
	std::string _studentID;
	std::string _major;

public:
	const double* get_score() { return _score; }
	const std::string get_id() { return _studentID; }
	const std::string get_major() { return _major; }
	void set_score(const double* score) { std::memcpy(_score, score, sizeof(score) / sizeof(score[0])); }
	void set_id(const std::string& id) { _studentID = id; }
	void set_major(const std::string& major) { _major = major; }
	void describe();
};


void Student::describe() {
	std::cout << "I am student" << std::endl;
}


//----------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------
// Teacher ( 派生类,继承自Person )

class Teacher :public Person {

public:
	Teacher(int age, char gender, std::string name,
			std::vector<std::string> lesson,
		    std::string id)
							:	Person(age, gender, name),
								_lesson(lesson),
								_teacherID(id)
	{}

	~Teacher() {}

private:
	std::vector<std::string> _lesson;
	std::string _teacherID;

public:
	const std::vector<std::string> get_lesson() { return _lesson; }
	const std::string get_id() { return _teacherID; }
	void set_lesson(const std::vector<std::string> lesson) { _lesson.assign(lesson.begin(), lesson.end()); }
	void set_id(const std::string& id) { _teacherID = id; }
	void describe();
};


void Teacher::describe() {
	std::cout << "I am Teacher" << std::endl;
}


//----------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------
// Principal ( 派生类,继承自Person )

class Principal :public Person {

public:
	Principal(int age, char gender, std::string name,
		std::string school)
		: Person(age, gender, name),
		_school(school)
	{}

	~Principal() {}

private:
	std::string _school;

public:
	const std::string get_school() { return _school; }
	void set_school(const std::string& school) { _school = school; }
	void describe();
};


void Principal::describe() {
	std::cout << "I am Teacher" << std::endl;
}




int main() {

	// 声明并初始化一个Person类
	double score[2] = { 90,100 };
	Person* P = new Student(13, '男', "chengzhen", score, "1402110", "软件工程");

	P->describe();

	std::cout << std::endl;
	std::cin.get();
}
以上代码的输出结果是什么:


比较奇怪呀,我们直观上来看,主函数中new了一个Student类型的对象,并进行了初始化,但是在调用describe函数的时候,却调用了基类的describe函数,屏蔽了子类的describe函数,造成了一种使用上的迷惑。为了能够让可以不同的子类当做基类来看,屏蔽不同子类之间的差异,使得基类可以按照赋值给它的子类的特性去运作,从而写出通用的代码,来适应需求的不断变化,C++支持“多态”这个比较重要的特性。接下来,我们来看一下,“多态”究竟该怎么实现?

2.6 多态的实现有哪些方式?

1)虚函数

完了,感觉又多了一个名词,但是没关系,我们可以一点点的来拨开多态的迷雾。什么是虚函数,虚函数是指函数前加上“virtual”这个关键字的函数叫做“虚函数”。虚函数是为了实现多态而产生的。还是上边的例子,我们只需要简单的添加一些内容,就可以实现多态。看下边:

#include <iostream>
#include <vector>
#include <cmath>
#include <string>




//----------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------
// Person ( 基类 )


class Person {

public:
	Person(int age, char gender, std::string name)
		:_age(age),
		 _gender(gender),
		 _name(name)
	{}

	virtual ~Person();

public:
	int  _age;
	char _gender;
	std::string _name;

public:
	const int get_age() { return _age; }
	const char get_gender() { return _gender; }
	const std::string get_name() { return _name; }
	void set_age(const int &value);
	void set_gender(const char &value);
	void set_name(const std::string &value);
	virtual void describe();
};


void Person::set_age(const int &value) {
	this->_age = value;
}

void Person::set_gender(const char &value) {
	this->_gender = value;
}

void Person::set_name(const std::string &value) {
	this->_name = value;
}

void Person::describe() {
	std::cout << "I am Person" << std::endl;
}

Person::~Person()
{
	//
}



//----------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------
// Student ( 派生类,继承自Person )

class Student :public Person {

public:
	Student(int age, char gender, std::string name,
			double *score,std::string ID,
			std::string major)
								:	Person(age,gender,name),
									_score(score),
									_studentID(ID),
									_major(major)
	{}

	~Student(){}

private:
	double *_score;
	std::string _studentID;
	std::string _major;

public:
	const double* get_score() { return _score; }
	const std::string get_id() { return _studentID; }
	const std::string get_major() { return _major; }
	void set_score(const double* score) { std::memcpy(_score, score, sizeof(score) / sizeof(score[0])); }
	void set_id(const std::string& id) { _studentID = id; }
	void set_major(const std::string& major) { _major = major; }
	virtual void describe();
};


void Student::describe() {
	std::cout << "I am student" << std::endl;
}


//----------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------
// Teacher ( 派生类,继承自Person )

class Teacher :public Person {

public:
	Teacher(int age, char gender, std::string name,
			std::vector<std::string> lesson,
		    std::string id)
							:	Person(age, gender, name),
								_lesson(lesson),
								_teacherID(id)
	{}

	~Teacher() {}

private:
	std::vector<std::string> _lesson;
	std::string _teacherID;

public:
	const std::vector<std::string> get_lesson() { return _lesson; }
	const std::string get_id() { return _teacherID; }
	void set_lesson(const std::vector<std::string> lesson) { _lesson.assign(lesson.begin(), lesson.end()); }
	void set_id(const std::string& id) { _teacherID = id; }
	virtual void describe();
};


void Teacher::describe() {
	std::cout << "I am Teacher" << std::endl;
}


//----------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------
// Principal ( 派生类,继承自Person )

class Principal :public Person {

public:
	Principal(int age, char gender, std::string name,
		std::string school)
		: Person(age, gender, name),
		_school(school)
	{}

	~Principal() {}

private:
	std::string _school;

public:
	const std::string get_school() { return _school; }
	void set_school(const std::string& school) { _school = school; }
	virtual void describe();
};


void Principal::describe() {
	std::cout << "I am Teacher" << std::endl;
}



int main() {

	// 声明并初始化一个Person类
	double score[2] = { 90,100 };
	Person* P = new Student(13, '男', "chengzhen", score, "1402110", "软件工程");

	P->describe();

	std::cout << std::endl;
	std::cin.get();
}
输出结果是:


可以看见,输出的结果是我们预想到的。我们创建了一个Student对象,但是是在基类Person中派生的,因此基类拥有了Student类的特性,调用discrube函数,使得调用的是子类的函数,其他类也一样:Person* P = new Teacher(),Person* P = new Principal()等等。

2)抽象类

带有纯虚函数的类,就是C++的抽象类。工厂模式使用的就是这种方式。我会在设计模式中以“工程模式”为例子来实现这种方法实现的多态。

总之一句话,多态的支持,使得我们能够屏蔽类的不同特性,而专注于使用。







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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值