面向对象介绍

介绍

结构化程序设计

  • pascal之父 结构化程序设计先驱 迪杰斯特拉
  • 程序 = 算法 + 数据结构
  • 程序是完成一定功能的一系列有序指令的集合
  • 这种设计方法是面向过程的,特点是数据与数据处理分离
  • 结构化程序设计是自顶向下,将系统视为分层的子程序的集合,可以将程序分为功能不同的模块,使得整个程序更有条理性,但是很多数据仍然属于整个程序,因而结构化程序设计思想还是需要有很多的全局变量,在某个地方进行更改,所以会对整个程序产生难以预料的影响。
  • 结构化程序设计的缺陷,其根源在于数据与数据处理的分离
    • 程序难以管理
    • 数据修改存在问题
    • 程序可重用性差
    • 用户要求难以在系统分析阶段准确定义,致使系统在交付使用时产生许多问题
    • 用系统开发每个阶段的成果来进行控制,不能适应事物变化的要求

面向对象程序设计

  • 面向将系统看成通过交互作用来完成特定功能的对象的集合,每个对象用自己的方法来管理数据也就是说只有对象内部的代码能够操作对象内部的数据
  • 程序 = 对象 + 对象 + 对象 + 发生消息 对象 = 算法 + 数据
  • 三个特性:
    • 封装
    • 继承
    • 多态

面向对象程序设计

  • 面向对象是认识事务的一种方法,是一种以对象为中心的思维方式
    • 对象 = 算法 + 数据结构
    • 程序 = 对象 + 对象 + … + 对象
  • 面向对象将数据和对数据的操作放在一起,形成一个相对独立的整理-对象,同类对象还可抽象出共性,形成类(class),一个类中的数据只能通过本类提供的方法进行处理,这些方法称为该类与外部的接口,对象之间通过消息(message)进行通讯。
  • 对象之间只能通过函数调用也就是发送消息来实现相互通信

封装

  • 封装是按照信息屏蔽的原则,把对象的属性和操作结合在一起,构成一个独立的对象
  • 通过限制对属性和操作的访问权限,可以将属性隐藏在对象内部,对外提供一定接口,在对象之外只能通过接口对对象进行操作
  • 封装性增加了对象的独立性,从而保证了数据的可靠性
  • 外部对象不能直接操作对象的属性,只能使用对象提供的服务

继承

  • 继承表达了对象的一般与特殊的关系,特殊类的对象具有一般类的全部属性和服务
  • 继续性大大简化了对问题的描述,大大提高了程序的可重用性

多态性

  • 多态性:同一个消息被不同对象接收时,产生不同的结果,即实现同一接口,不同方法
  • 一般类中定义的属性和服务,在特殊类中不改变其名字,但通过各自不同的实现后,可以具有不同的数据类型或不同的行为
  • 多态使我们能够以一致的观点来看待不同(但又大相径庭的)对象,同一个消息发送到不同的对象,就会呈现出不同的行为

继承与多态

继承和多态的组合,可以生成很多相似但又独一无二的对象。

面向对象编程方法的特性

  • 程序设计的重点在数据而不是函数
  • 程序由对象组成,建立对象的目的不是为了完成一个步骤,而是为了描述某个事物在整个解决问题的步骤中的行为
  • 对象之间通过相互协作来完成功能
  • 函数与相关的数据紧密结合
  • 数据可以被隐藏
  • 很容易扩充新的数据和函数

类与对象(一)

类声明

//类是一种用户自定义的类型,声明形式:
class 类名称
{
public:
公有成员(外部接口)
private:
私有成员
protected:
保护成员
};

公有、私有、保护成员

  • 在关键字 public 后面声明,它们是类与外部的接口,任何外部函数都可以访问公有类型数据和函数
  • 在关键字 private 后面声明,只允许本类中的函数访问,而类外部的任何函数都不能访问
  • 在关键字 protected 后面声明,与 private 类似,其差别表现在继承与派生时对派生类的影响不同, protected 在派生类是可以访问的。

数据抽象和封装

  • 数据抽象是一种依赖于接口和实现分离的编程(和设计)技术,类设计者必须关系类是如何实现的,但使用该类的程序员不必了解这些细节,使用者只要抽象的考虑该类型做什么,而不必具体的考虑该类如何工作。

类与对象(二)

  • 内联函数可以提高效率,编译的时候将代码直接嵌入到调用的地方,从而减少函数调用的开销,但是体积增大,是以空间换时间
  • 内联函数仅仅是给编译器一个提示,如果函数中有 switch for 则不会展开.

内联成员函数

两种实现方式

  • 在类外部添加 inline 关键字实现
  • 在类内直接实现函数,不需要加关键字

成员函数的重载及其缺省参数

函数的重载要具有相同的作用域

声明函数的可以设置缺省参数,注意二义性

类与结构体

class 和 struct 的区别:在未指定访问权限时,class 默认是私有的, struct 默认是公有的

隐含的 this 指针

  • 成员函数有一个隐含的附加形参,即指向该对象的指针,这个隐含的形参叫做 this 指针
  • 使用 this 指针保证了每个对象可以拥有不用的数据成员,但处理这些成员的代码可以被所有对象共享
  • t1.Init(&t1, 10, 20, 30) &t1 就是 this 指针
  • t2.Init(&t2, 1, 2, 3)

类与对象(三)

类作用域

  • 每个类都定义了自己的作用域称为类作用域
  • 类作用域中说明的标识符只要类中可见
  1. 块作用域
  2. 文件作用域
  3. 函数原型作用域
  4. 函数作用域
  5. 类作用域
#include <iostream>
using namespace std;

class Test
{
public:
int num_;
};

//num_ = 20; Error num_的作用域在类内部

int num_ = 20; // num_的作用域是文件作用域,与类中的num_是不同的作用域

int add(int a, int b); // a, b 两个标识符的作用域为函数原型作用域
void test();
int main()
{
int num_ = 10; //num_ 为块作用域
{
int num_ = 100; //num_ 为块作用域
cout << num_ << endl;
}
cout << num_ << endl;
cout << ::num_ << endl;
test();
return 0;
}

int add(int a, int b) // 形参 a b 也算是块作用域
{
return a + b;
}
void test()
{
LABEL1:
cout << "label1" << endl;
goto LABEL3;
LABEL2:
cout << "label2" << endl;
goto LABEL1;
LABEL3:
cout << "label3" << endl;
goto LABEL2;
}

前向声明

  • C++ 中类必须先定义,才能够实例化
  • 两个类需要相互引用形成一个“环形”引用时,无法先定义使用,这时候需要用到前向声明
  • 前向声明的类不能实例化,只能用指针或引用 A* a_;

嵌套类

  • 外围类需要使用嵌套类对象作为底层实现,并且该嵌套类只能用于外围类的实现,且同时可以对用户隐藏该底层实现。
  • 从作用域的角度看,嵌套类被隐藏在外围类之中,该类名只能在外围类中使用,如果在外围类的作用域使用该类名时,需要加名字限定
  • 嵌套类中的成员函数可以在它的类体外定义
  • 嵌套类的成员函数对外围类的成员没有访问权,反之亦然
  • 嵌套类仅仅只是语法上的嵌入

局部类

  • 类也可以定义在函数体内,这样的类被称为局部类(local class),局部类只有在定义它的局部域内可见
  • 局部类的成员函数必须被定义在类体中
  • 局部类中不能有静态成员