cpp_5_1_面向对象_0_overview

面向对象的核心要点

1.Introduction to object-oriented programming 面向对象编程
2.Introduction to classes
3.Member functions 成员函数
4.Const class object and const member functions
5.Public and private mmbers and access specifiers
6.Accesss functions
7.Member functions returning references to data members
8.The benefits of data hiding
9.Introduction to constructors
10.Constructor member initializer lists
11.Default constructors
12.Delegating constructors and default arguments
13.Temporary class objects
14.Introduction to the copy constructor
15.Class initialization and copy elision
16.Converting constructors and the explicit keyword

Procedural programming 过程式编程

an object: a piece of memory that can be used to store values. An object with a name is called a variable.

C++ programs have consisted of sequential lists of instructions to the computer that define data (via objects) and operations performed on that data (via functions containing statements and expressions).

In procedural programming, the focus is on creating “procedures” (which in C++ are called functions) that implement our program logic. We pass data objects to these functions, those functions perform operations on the data, and then potentially return a result to be used by the caller.

In procedural programming, the functions and the data those functions operate on are separate entities. The programmer is responsible for combining the functions and the data together to produce the desired result. This leads to code that looks like this:

eat(you, apple);

intuitively,
1.回顾下 object 和 variable 的定义: 一个 object 我们定义为一小段可以储存值的内存. 一个有名字的 object 我们称之为变量. 一切的代码和程序执行都是围绕着各种 object 进行操作
2.cpp 程序将一系列指令送入到计算机, 这些指令本质都是我们定义的 [数据] 和 [运算], 在cpp里面, 数据都是通过 object 定义的, 运算是通过 function 定义的 (函数里面包括了各种声明和表达式).
3.在 procedural programming (过程式编程) 里面, 我们聚焦在构造 “procedures” (其实就是函数) 来实现我们要的程序逻辑: 我们将数据 objects 传入到这些 function 里面, 然后这些函数对这些数据进行各种操作, 最终 (可能) 返回函数调用的结果
4.在这种 procedural programming 这种范式下, 函数和被函数操纵的数据是相互分离的. 程序员需要将二者组合起来才会产生我们要的结果, 简单来说, 调用的函数的形式都是

函数(调用函数的主体, 数据)

What is object-oriented programming? 什么是面向对象编程

In object-oriented programming (often abbreviated as OOP), the focus is on creating program-defined data types that contain both properties and a set of well-defined behaviors. The term “object” in OOP refers to the objects that we can instantiate from such types. This leads to code that looks more like this:

you.eat(apple);

This makes it clearer who the subject is (you), what behavior is being invoked (eat()), and what objects are accessories to that behavior (apple).

Because the properties and behaviors are no longer separate, objects are easier to modularize, which makes our programs easier to write and understand, and also provides a higher degree of code reusability. These objects also provide a more intuitive way to work with our data by allowing us to define how we interact with the objects, and how they interact with other objects.

intuitively,
1.在 oop (面向对象) 编程的范式下, 我们目的是要构造一种数据类型 (data types), (这里的 data types 其实指的是 struct/class), 数据类型包含[属性 (proberties) ] 和 [一系列定义好的行为(well-defined behaviors)]. “object” 在 oop 里面指的是我们从数据类型中执行实例化, 也就是”对象”, 然后调用函数就变成了类似于 xx.function(xx) 的形式
2.相比于面向过程的范式, oop 范式能够更清楚地明确出来谁是调用函数的主体, 谁是主体的行为
3.在 oop 范式下, [属性] 和 [行为] 不再相互分离, 而是绑定在一起; objects 实现了更好的模块化的效果, 使得代码更容易被理解, 且达到了更高层次的代码复用性
4.objects (对象) 提供了一个更直观的数据操作的抽象, 我们可以去定义对象, 并且去定义多个对象之间的交互

A procedural v.s. OOP-like example 一个面向过程和面向对象的例子的对比

下面我们通过一个例子去对比面向过程和面向对象对于对于数据操纵的不同, 假设我们有三种动物的类型, 动物有返回动物的名称以及动物的腿的个数两个函数, 按照 procedural 范式来写代码如下

#include <iostream>
#include <cstring>

enum AnimalType {
  cat,
  dog,
  chicken,
};

std::string animalName(AnimalType type) {
  switch (type) {
    case cat: return "cat"; break;
    case dog: return "dog"; break;
    case chicken: return "chicken"; break;
    default:  return ""; break;
  }
}

int numLegs(AnimalType type) {
  switch (type) {
    case cat: return 4; break;
    case dog: return 4; break;
    case chicken: return 2; break;
    default:  return 0; break;
  }
}

int main() {
  constexpr AnimalType animal{cat};
  std::cout << "A " << animalName(animal) << " has " << numLegs(animal) << " legs\n";
  return 0;
}

这个代码看起来是可以执行的, 但是加上我们现在要新加一个动物, 比如 snake, 为了增加这个新的动物, 我们需要修改 AnimalType, numLegs(), animalName(); 但是其实我们想一下, 不管新增多少个动物, 我们都只是要确定他的名字和腿的数量; 同时, 不管有多少个动物, 他们本质都是一类东西, 都是动物 (这种data type); 因此我们改成 oop 的写法:

#include <iostream>
#include <cstring>

struct Animal {
  std::string name{};
  int numLegs{};
  Animal (std::string name, int numlegs) {
    this->name = name;
    this->numLegs = numlegs;
  }
};

int main() {
  std::string catName = "kitty";
  std::string chickenName = "joe";
  std::string dogName = "lucy";
  Animal cat{catName, 4};
  Animal chicken{chickenName, 2};
  Animal dog{dogName, 4};
  std::cout << cat.name << " has " << cat.numLegs << " legs\n";
  std::cout << chicken.name << " has " << chicken.numLegs << " legs\n";
  std::cout << dog.name << " has " << dog.numLegs << " legs\n";
  return 0;
}

在这种oop的写法之下, 比我们只需要对单独的 struct 进行操作

OOP brings other benefits to table 面向对象编程带来了其他优势

In school, when you submit your programming assignments, your work is essentially done. Your professor or teacher’s assistant will run your code to see if it produces the correct result. It either does or doesn’t, and you are graded accordingly. Your code is likely discarded at that point.

when you submit your code into a repository that is used by other developers, or into an application that’s used by real users, it’s an entirely different ballgame. Some new OS or software release will break your code. Users will find some logic error you made. A business partner will demand some new capability. Other developers will need to extend your code without breaking it. Your code needs to be able to evolve, perhaps significantly, and it needs to be able to do so with minimal time investment, minimal headaches, and minimal breakage.

The best way to address these is by keeping your code as modular (and non-redundant) as possible. To assist with this, OOP also brings a number of other useful concepts to the table: inheritance, encapsulation, abstraction, and polymorphism.

intuitively,
1.在学校学习 cs 课程的时候, 当我们提交了代码作业 (学习任务实质上也就做完了). 老师会跑一下代码检查下结果是否正确然后打个分数. 在学校交作业这种模式下, 代码跑完然后打完分之后其实也被丢弃了;
2.去到公司里面干活时候, 我们提交代码到仓库, 会有其他的同事使用我们开发的代码继续开发, 这种情况和在学校就截然不同了. 比如:
(i). 某些新的操作系统或者软件版本发布会破坏你的代码, 例如你用的是python2.7写的一些逻辑, 现在要升级到python3.5
(ii). 用户也会发现你搞出来的错误
(iii). 老板也总需要你增加一些新的功能
(iv). 其他同时可能需要在你的代码上继续开发

所以, 我们写的代码需要具备扩展性, 尤其是面向是大版本大规模的改动, 并且要求我们采用尽可能小的改动满足这些要求, 解决上述这些情况为代表的扩展性问题的一种组织代码的原则就是

keeping our code as modular as possible (尽可能保持我们的代码模块化)

oop 给我们引入了一系列代码模块化的操作: inheritance, encapsulation, abstraction, polymorphism. 能够让我们更好地将代码具备更强的模块化的能力


转载请注明来源, from goldandrabbit.github.io

💰

×

Help us with donation