计协教程(2): 面向对象程序设计

简述

本节简单介绍一下什么是面向对象的程序设计思路。

首先对其意义做介绍,也就是为什么要面向对象。抽象意义上一个对象就是用来描述、操作一个具体事物控制实体。而具体事物是显然不断在变化升级的,因此控制实体也需要不断升级以适配事物的新发展。
而通过面向对象的程序设计,可以极大提高控制实体的代码复用程度,减少在更新换代中需要写的代码量。

比如说一个游戏的主角可以转职,转职前只能移动、跳跃和使用近战攻击,
转职后可以远程了,使用面向对象的程序设计思路,
以主角作为一个对象,转职前移动跳跃的代码完全可以不必写
(连复制都不必),
可以直接复用,而只需要添加一个远程攻击的代码即可。

上面所述是面向对象程序设计最主要的优势,即使得对于某事物的更新迭代变得更容易。当然还有很多其他优势,为了减少理解量暂时不提。

面向对象程序的主要代码工作就是描述一类对象,也就是写,相当于画蓝图。而写完后的一个程序的运行就是根据创建各种各样的对象完成不同的任务。

对象是类的一个实例,类是创建对象的模板

描述一类对象的主要工作在于:

1.定义这类对象需要的各种数据,称为成员变量。
2.定义这类对象需要对各种数据进行的操作,称为成员函数。

这里用一个例子简单展示一下,这里使用C++语言。

面向对象的语言就是提供实现面向对象程序设计思想的语言基础,C++、Java、Python都是经典的面向对象语言

#include<iostream>
using namespace std;

class Calc//一个类,这个类用来处理a+b问题
{
public:
    int a, b;//两个成员变量
    Calc(){//一个对象的构造函数,这里无参,函数内容就是初始化a、b为0
        a=b=0;
    };
    Calc(int a,int b){//重载一个指定了a、b参数的构造方法。
        this->a = a;//这里this是表示指向自己这个对象的地址
        this->b = b;
    }
    ~Calc();

    int getPlusAnwser(){//一个普通成员函数,返回计算结果
        return a + b;
    }
};

int main(){
    Calc c1;//默认无参构造
    c1.a = 100;//手动设置参数
    c1.b = 200;
    Calc c2(10, 20);//实例化一个类,即创建对象,采用有参构造直接初始化a、b参数
    cout<<c1.getPlusAnwser()<<endl;
    cout<<c2.getPlusAnwser()<<endl;//通过对象调用成员函数,使用的参数就是本对象内部的参数
    return 0;
}

得出来的结果是

300
30

更具体的类编写规则可以到网上找:
https://www.runoob.com/cplusplus/cpp-classes-objects.html

封装

刚刚我们演示了一个最简单的类的编写与对象的创建,并完成了a+b问题
我们介绍进阶一些的面向对象概念,主要是面向对象程序设计中最重要的三个特性:封装、继承和多态。

首先是封装,主要有两层概念:

1. 数据的储存和数据的操作封装在一起,构成一个统一独立实体
上面的例子已经能体现这一点了。
2. 数据被隐藏/保护在抽象数据类型(自定义类)的内部
只保留一些对外接口与外部发生联系,安全性更高,也避免错误的使用。
这主要是通过限制访问权限等操作实现

下面用一个简单的例子说明一下第二点的优势:


#include<iostream>
using namespace std;

class Student
{
private:
    int score;

public:
    Student(){score = 0;};
    Student(int score){
        if(score<0 || score >100){//score必然在[0,100]区间
            this->score = 0;
        }else{
            this->score = score;
        }
    }
    ~Student(){};

    void setScore(int score){
        if(score<0 || score >100){
            this->score = 0;
        }else{
            this->score = score;
        }
    }
    int getScore(){
        return this->score;
    }
};

int main(){
    Student s;
    s.setScore(101);
    cout<<s.getScore()<<endl;
    s.setScore(99);
    cout<<s.getScore()<<endl;
    return 0;
}

注意这里将Student类的score成员对象设定为private,说明只有对象自己能够访问此成员,
这样在main函数里面就无法使用s.score = 101直接赋值
只能通过调用s.setScore(101),通知对象帮忙设定指定值
而此时就能在成员函数里判断要设定的这个值是否有问题等,防止错误的赋值

上例结果如下:

0
99

继承

继承是实现代码复用的最主要特性
子类继承父类,会继承父类的非private成员变量与方法。
也举个例子:
比如如果不采用继承,描述两个类StudentTeacher


#include<iostream>
#include<cstring>
using namespace std;

class Student
{
private:
    string name;
    int score;

public:
    Student(string name, int score){
        this->name = name;
        this->score = score;
    }
    ~Student(){};//析构函数,当销毁对象时调用

    int getScore(){//一个普通成员函数,返回计算结果
        return this->score;
    }
    string getName(){
        return this->name;
    }
};

class Teacher{
private:
    string name;
    int salary;
public:
    Teacher(string name, int salary){
        this->name = name;
        this->salary = salary;
    }
    ~Teacher(){};
    
    string getName(){
        return this->name;
    }
    int getSalary(){
        return this->salary;
    }
};
int main(){
    Student s("CakeCN", 60);
    Teacher t("Opela", 2000);
    cout<<s.getName()<<" "<<s.getScore()<<endl;
    cout<<t.getName()<<" "<<t.getSalary()<<endl;
    return 0;
}

运行结果如下:

CakeCN 60
Opela 2000

通过继承实现,这里注意到StudentTeacher都有同样的Name属性,抽象出一个Person类作为两者的父类,这样就不用写两遍输出Name的代码了。
当然因为重复度不高,所以代码量区别不大,不过如果共性的属性agegendarheight很多,这种复用就很优越。


#include<iostream>
#include<cstring>
using namespace std;
class Person{
protected:
    string name;
public:
    Person(string name){
        this->name = name;
    }
    string getName(){
        return this->name;
    }
};

class Student : public Person //用public继承,不改变父类的成员访问权限
{
private:
    int score;
public:
    Student(string name, int score):Person(name){
        this->score = score;
    }
    ~Student(){};
    int getScore(){
        return this->score;
    }
};

class Teacher : public Person
{
private:
    int salary;
public:
    Teacher(string name, int salary):Person(name){
        this->salary = salary;
    }
    ~Teacher(){};
    int getSalary(){
        return this->salary;
    }
};
int main(){
    Student s("CakeCN", 60);
    Teacher t("Opela", 2000);
    cout<<s.getName()<<" "<<s.getScore()<<endl;
    cout<<t.getName()<<" "<<t.getSalary()<<endl;
    return 0;
}

多态

多态是面向对象的核心特性,它尽管没有继承那么好的直观理解,但与之相当重要。
相对于继承的提供了一种容易描述事物的发展性的能力,多态则是描述事物在发展中发生变化而需要对其的多样性给予的支持能力。

下面举个例子,比如来了一个人,但是事先不知道这个人是学生还是老师,又需要能够得出这个人的信息,就可以使用下面两种多态能力:父类指针指向子类对象以及重写父类的同名函数


#include<iostream>
#include<cstring>
using namespace std;
class Person{
protected:
    string name;
public:
    Person(string name){
        this->name = name;
    }
    string getName(){
        return this->name;
    }
    //虚函数,说明子类需要重写这个函数,各自输出不同的信息
    virtual void info(){}
};

class Student : public Person
{
private:
    int score;
public:
    Student(string name, int score):Person(name){
        this->score = score;
    }
    ~Student(){};
    int getScore(){
        return this->score;
    }
    void info(){
        cout<<"im Student "<<name<<" score is:"<<score<<endl;
    }
};

class Teacher : public Person
{
private:
    int salary;
public:
    Teacher(string name, int salary):Person(name){
        this->salary = salary;
    }
    ~Teacher(){};
    int getSalary(){
        return this->salary;
    }
    void info(){
        cout<<"im Teacher "<<name<<" salary is:"<<salary<<endl;
    }
};
int main(){
    Person* p;
    p = new Student("CakeCN", 60);
    p->info();
    p = new Teacher("Opela", 2000);
    p->info();
    return 0;
}

运行结果是

im Student CakeCN score is:60
im Teacher Opela salary is:2000

多态还有其它的体现点,不过上面的例子是比较经典的两种多态体现(重载广义上来说也可算是一种多态体现,但是并没有太大面向对象的特质)。

更重要的优势

比复制黏贴更强的代码复用,意味着你抄代码变得更容易了——事实上现在写各种需求基本上都是先去git找有没有相似的需求然后自己改。
也就是拿别人写好的库,直接有什么自己想添加的内容继承添加即可,既可以防止对别人的库的破坏,又利于自己实现自定义的需求。
以及更抽象的对面向对象的认识,就需要更多代码的训练培养了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值