您的位置:首页 > 其它

<5> 面向对象到底有什么(中)?

2018-01-11 14:03 267 查看
在<3> 面向对象到底有社么(上)一文中,我们说了下关于面向对象和面向过程的区别和优劣性。在面向对象里边,也谈了下关于“面向对象三大特性”的其中一个特性“封装性”的简单理解。在这一文中,我们主要一起来了解下关于面向对象的第二个特性“继承”的理解,一起来看下“继承”到底是什么?继承到底有什么作用?以及“继承”在什么情况下会用到?继承的优点在哪里?

2.2 ”继承“到底是什么?为什么要有它这个东西?

我是觉得,现在的名称翻译还是挺符合“顾名思义”的原则的,继承在我们一般人的眼里,就代表了“依法拿到遗产”、“把前人的文化、知识传承过来”等意思,在高级程序设计语言这里,其实也有类似的意味。

还是接着我们上一篇文章的“Person”类作为例子,接着说。实际上,在我们的项目中,“人”只是一个比较宽泛的“类别”,在这个社会群体中,“学生”,“老师”,“校长”等等社会职业属于“人”这个类型,但是这些社会职业本身也都是单独的“类别”。假设:我们在“Person”类里边添加关于“学生”,“老师”,“校长”的一些信息,结果会是这样的:

//----------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------
// 类的封装
class Person{

public:
Person(int age, char gender, std::string name)
:_age(age),
_gender(gender),
_name(name)
{
_score = new double[10];
}

~Person();

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

// 学生
double *_score;
std::string _studentID;
std::string _major;

// 老师
std::vector<std::string> _lesson;
std::string _teacherID;

// 校长
std::string _school;
//···
//···
//···

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 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;
}

Person::~
4000
Person()
{
//
}

int main() {

// 声明一个Person类型的对象
// 请注意:对象的概念在这里开始出现,因为Person是一个集合,一个类型,那么类型的一个一个实际的例子,就是对象
Person m_person(25, '男', "chengzhen");

// 获得年龄
m_person.get_age();

// 获得性别
m_person.get_gender();

// 获得姓名
m_person.get_name();

// 设置年龄
m_person.set_age(30);

// 设置性别
m_person.set_gender('nv');

// 设置姓名
m_person.set_name("Charmain");

std::cin.get();
}

如果我们在某个地方只用学生这个“类别”,我们就不得不来一次“Person student(25,'男',“who”)“一次,但是我们发现,在创建一个对象并初始化的时候,类已经为我们创建好了”老师“,”校长“等社会角色身上存在的一些特性(老师教授的”课“有哪些,校长管理的是”哪个学校“等等)。而我们明白的是,学生并不需要知道具备这些特性,因为他们只需要做好自己,了解自己的特性就好。由于我们把这些内容都融合在一个类里边,所以每次在创建对象的时候,就会有多余的数据被创建,比如:std::vector<std::string>
_lesson、std::string _school等等,造成代码冗余,工程文件过大,不易管理、可读性不高。当然,我们也可以这么来写设计类:


//----------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------
// 类的封装
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);
};

//----------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------
// 类的封装
class Student {

public:
Student(int age, char gender, std::string name)
:_age(age),
_gender(gender),
_name(name)
{
_score = new double[10];
}

~Student();

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

// 学生
double *_score;
std::string _studentID;
std::string _major;

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);
};

//----------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------
// 类的封装
class Teacher {

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

~Teacher();

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

// 老师
std::vector<std::string> _lesson;
std::string _teacherID;

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);
};

//----------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------
// 类的封装
class Principal {

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

~Principal();

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

// 校长
std::string _school;
//···
//···
//···

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);
};

看见上边的内容,可以发现每个一共有四个类,每个类中都有相同的内容:年龄、性别、姓名、获取年龄、获取性别、获取姓名,如果以后需要添加内容,也许会有数十个甚至上百个成员函数或者成员变量是相同的。会导致代码的复用性不高,过于冗余,不够精简。因此,这个时候,我们可以用上我们的面向对象的第二个特性”继承“了。

2.3 ”继承“该怎么用?

我们依然是以”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 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;
}

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; }
};

//----------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------
// 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; }
};

//----------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------
// 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; }
};

int main() {

// 声明一个Person类型的对象
// 请注意:对象的概念在这里开始出现,因为Person是一个集合,一个类型,那么类型的一个一个实际的例子,就是对象
Person m_person(25, '男', "chengzhen");

// 获得年龄
m_person.get_age();

// 获得性别
m_person.get_gender();

// 获得姓名
m_person.get_name();

// 设置年龄
m_person.set_age(30);

// 设置性别
m_person.set_gender('nv');

// 设置姓名
m_person.set_name("Charmain");

std::cin.get();
}

这样看起来,不管是Student、Teacher、还是Principal类,都具备了Person的属性,同时也拥有了自己的特性,展现了三个不同人群之间的差异,但是同时,这种“is-a”的关系,也是继承的一个重要关系,即:派生类也是一个基类。并且在使用类的时候,按需使用。对于功能的扩展好,都比较明晰,减少了冗余代码,增加了可读性,这些也是“继承”能够被支持的重要原因之一。

未完,待续。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: