剖析C++的面向对象编程思想

面向对象的程序设计
面向对象编程(Object Oriented Programming,OOP,面向对象程序设计) 的主要思想是把构成问题的各个事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙一个事物在整个解决问题的步骤中的行为。

面向过程就是分析出解决问题所需要的步骤,然后用函数逐步实现,再依次调用就可以了。

面向对象和面向过程是两种不同的编程思想,没有哪一种绝对完美,要根据具体需求拟定开发方案。例如,开发一个小型软件或应用程序,工程量小,短时间内即可完成,完全可以采用面向过程的开发方式,使用面向对象,反而会增加代码量,降低开发效率。

面向过程的编程语言(如C语言)不能创建类和对象,不能用面向对象的思想来开发程序;面向对象的编程语言(如C++、PHP等)保留了面向过程的关键字和语句,仍然可以采用面向过程的思想来开发程序。

面向对象是面向过程的补充和完善。

注意,不要“死磕”概念上的理解,很多有经验的程序员甚至都不能完全解释清楚面向对象和面向过程的区别,要重在实践,不断揣摩编程语言的思想。
类和对象的基本概念

为了方便说明,我们将从现实生活中的实例入手。

我们知道,工业上使用的铸件(电饭锅内胆、汽车地盘、发动机机身等)都是由模子铸造出来的,一个模子可以铸造出很多相同的铸件,不用的模子可以铸造出不同的铸件。这里的模子就是我们所说的“类”,铸件就是我们所说的“对象”。

类,是创建对象的模板,一个类可以创建多个相同的对象;对象,是类的实例,是按照类的规则创建的。
属性和方法

由模子铸造出来的铸件(对象),有很多参数(长度、宽度、高度等),能完成不同的操作(煮饭、承重、保护内部零件等)。这里的参数就是对象的“属性”,完成的操作就是对象的“方法”。

属性是一个变量,用来表示一个对象的特征,如颜色、大小、重量等;方法是一个函数,用来表示对象的操作,如奔跑、呼吸、跳跃等。

对象的属性和方法统称为对象的成员。
类的继承

一个类(子类)可以继承另一个类(父类)的特征,如同儿子继承父亲的DNA、性格和财产。

子类可以继承父类的全部特征,也可以继承一部分,由程序灵活控制。

C++面向对象程序设计举例
这里我们将通过几个简单的例子来演示如何站在面向对象的角度设计程序,以及使用类的好处。

【例】最简单的例子。

#include <iostream>
using namespace std;
class Time //定义Time类
{
public : //数据成员为公用的
  int hour;
  int minute;
  int sec;
};
int main( )
{
  Time t1;//定义t1为Time类对象
  cin>>t1.hour;//输入设定的时间
  cin>>t1.minute;
  cin>>t1.sec;
  //输出时间:
  cout<<t1.hour<<":"<<t1.minute<<":"<<t1.sec<<endl;
  return 0;
}

运行情况如下:

1232 43
12:32:43

几点注意:
1) 在引用数据成员hour,minute,sec时不要忘记在前面指定对象名。

2) 不要错写为类名,如写成
 Time.hour,Time.minute,Time.sec
是不对的。因为类是一种抽象的数据类型,并不是一个实体,也不占存储空间,而对象是实际存在的实体,是占存储空间的,其数据成员是有值的,可以被引用的。

3) 如果删去主函数的3个输入语句,即不向这些数据成员赋值,则它们的值是不可预知的。

【例】引用多个对象的成员。

1) 程序(a)

#include <iostream>
using namespace std;
class Time
{
public :
  int hour;
  int minute;
  int sec;
};
int main( )
{
  Time t1;//定义对象t1
  cin>>t1.hour;//向t1的数据成员输入数据
  cin>>t1.minute;
  cin>>t1.sec;
  cout<<t1.hour<<":"<<t1.minute<<":"<<t1.sec<<endl;//输出t1中数据成员的值
  Time t2;//定义对象t2
  cin>>t2.hour;//向t2的数据成员输入数据
  cin>>t2.minute;
  cin>>t2.sec;
  cout<<t2.hour<<":"<<t2.minute<<":"<<t2.sec<<endl;//输出t2中数据成员的值
  return 0;
}

运行情况如下:

1032 43
10:32:43
22 32 43
22:32:43

程序是清晰易懂的,但是在主函数中对不同的对象一一写出有关操作,会使程序冗长。为了解决这个问题,可以使用函数来进行输入和输出。见程序(b)。

2) 程序(b)

#include <iostream>
using namespace std;
class Time
{
public :
  int hour;
  int minute;
  int sec;
};
int main( )
{
  void set_time(Time&);//函数声明
  void show_time(Time&);//函数声明
  Time t1;//定义t1为Time类对象
  set_time(t1);//调用set_time函数,向t1对象中的数据成员输入数据
  show_time(t1);//调用show_time函数,输出t1对象中的数据
  Time t2;//定义t2为Time类对象
  set_time(t2);//调用set_time函数,向t2对象中的数据成员输入数据
  show_time(t2);//调用show_time函数,输出t2对象中的数据
  return 0;
}
void set_time(Time& t) //定义函数set_time,形参t是引用变量
{
  cin>>t.hour;//输入设定的时间
  cin>>t.minute;
  cin>>t.sec;
}
void show_time(Time& t) //定义函数show_time,形参t是引用变量
{
  cout<<t.hour<<":"<<t.minute<<":"<<t.sec<<endl;//输出对象中的数据
}

运行情况与程序(a)相同。

3) 程序(c)
可以对上面的程序作一些修改,数据成员的值不再由键盘输入,而在调用函数时由实参给出,并在函数中使用默认参数。将程序(b)第8行以下部分改为:

int main( )
{
  void set_time(Time&,int hour=0,int minute=0,int sec=0);//函数声明
  void show_time(Time&);//函数声明
  Time t1;
  set_time(t1,12,23,34);//通过实参传递时、分、秒的值
  show_time(t1);
  Time t2;
  set_time(t2);//使用默认的时、分、秒的值
  show_time(t2);
  return 0;
}
void set_time(Time& t,int hour,int minute,int sec)
{
  t.hour=hour;
  t.minute=minute;
  t.sec=sec;
}
void show_time(Time& t)
{
  cout<<t.hour<<":"<<t.minute<<":"<<t.sec<<endl;
}

程序运行时的输出为:

12:23:34 (t1中的时、分、秒)
0:0:0 (t2中的时、分、秒)

以上两个程序中定义的类都只有数据成员,没有成员函数,这显然没有体现出使用类的优越性。在下面的例子中,类体中就包含了成员函数。

【例】改用含成员函数的类来处理。

#include <iostream>
using namespace std;
class Time
{
public :
  void set_time( );//公用成员函数
  void show_time( );//公用成员函数
private : //数据成员为私有
  int hour;
  int minute;
  int sec;
};
int main( )
{
  Time t1;//定义对象t1
  t1.set_time( );//调用对象t1的成员函数set_time,向t1的数据成员输入数据
  t1.show_time( );//调用对象t1的成员函数show_time,输出t1的数据成员的值
  Time t2;//定义对象t2
  t2.set_time( );//调用对象t2的成员函数set_time,向t2的数据成员输入数据
  t2.show_time( );//调用对象t2的成员函数show_time,输出t2的数据成员的值
  return 0;
}
void Time::set_time( ) //在类外定义set_time函数
{
  cin>>hour;
  cin>>minute;
  cin>>sec;
}
void Time::show_time( ) //在类外定义show_time函数
{
  cout<< hour<<":"<< minute<<":"<< sec<< endl;
}

运行情况与例8.2中的程序(a)相同。

几点注意:
在主函数中调用两个成员函数时,应指明对象名(t1,t2)。表示调用的是哪一个对象的成员函数。
在类外定义函数时,应指明函数的作用域(如void Time∷set_time( ))。在成员函数引用本对象的数据成员时,只需直接写数据成员名,这时C++系统会把它默认为本对象的数据成员。也可以显式地写出类名并使用域运算符。
应注意区分什么场合用域运算符“∷”,什么场合用成员运算符“.”,不要搞混。

【例】找出一个整型数组中的元素的最大值。这个问题可以不用类的方法来解决,现在用类来处理,读者可以比较不同方法的特点。

#include <iostream>
using namespace std;
class Array_max //声明类
{
public : //以下3行为成员函数原型声明
  void set_value( ); //对数组元素设置值
  void max_value( ); //找出数组中的最大元素
  void show_value( ); //输出最大值
private :
  int array[10]; //整型数组
  int max; //max用来存放最大值
};
void Array_max::set_value( ) //成员函数定义,向数组元素输入数值
{
  int i;
  for (i=0;i<10;i++)
   cin>> array[i];
}
void Array_max::max_value( ) //成员函数定义,找数组元素中的最大值
{
  int i;
  max=array[0];
  for (i=1;i<10;i++)
   if(array[i]> max) max=array[i];
}
void Array_max::show_value( ) //成员函数定义,输出最大值
{
  cout<< "max="<< max;
}
int main( )
{
  Array_max arrmax; //定义对象arrmax
  arrmax.set_value( ); //调用arrmax的set_value函数,向数组元素输入数值
  arrmax.max_value( ); //调用arrmax的max_value函数,找出数组元素中的最大值
  arrmax.show_value( ); //调用arrmax的show_value函数,输出数组元素中的最大值
  return 0;
}

运行结果如下:

12 12 39 -34 17 134 045 -91 76 (输入10个元素的值)
max=134 (输入10个元素中的最大值)

请注意成员函数定义与调用成员函数的关系,定义成员函数只是设计了一组操作代码,并未实际执行,只有在被调用时才真正地执行这一组操作。

可以看出: 主函数很简单,语句很少,只是调用有关对象的成员函数,去完成相应的操作。在大多数情况下,主函数中甚至不出现控制结构(判断结构和循环结构),而在成员函数中使用控制结构。在面向对象的程序设计中,最关键的工作是类的设计。所有的数据和对数据的操作都体现在类中。只要把类定义好,编写程序的工作就显得很简单了。

(0)

相关推荐

  • c++ 面向对象的类设计

    类的设计在于用恰到好处的信息来完整表达一个职责清晰的概念,恰到好处的意思是不多也不少,少了,就概念就不完整:多了,就显得冗余,累赘,当然特例下,允许少许的重复,但是,这里必须要有很好的理由.冗余往往就意味着包含了过多的信息,概念的表达不够精准,好比goto,指针,多继承这些货色,就是因为其过多的内涵,才要严格限制其使用.好像,more effective c++上说的,class的成员函数,应该是在完整的情况下保持最小化.但是,这里我们的出发点,是成员数据的完整最小化. 最小化的好处是可以保持概

  • 分享一下8年C++面向对象设计的经验体会

    六年前,我刚热恋"面向对象"(Object-Oriented)时,一口气记住了近十个定义.六年后,我从几十万行程序中滚爬出来准备写点心得体会时,却无法解释什么是"面向对象",就象说不清楚什么是数学那样.软件工程中的时髦术语"面向对象分析"和"面向对象设计",通常是针对"需求分析"和"系统设计"环节的."面向对象"有几大学派,就象如来佛.上帝和真主用各自的方式定义了这个

  • 关于C++面向对象设计的访问性问题详解

    前言 最近在看Scott Meyers大神的<Effective C++>和<More Effective C++>,虽然这两本书都是古董级的教参了(当然针对C++11/C++14作者所更新的<Modern Effective C++>英文已经发售了,不过还没中文翻译版本),但是现在看来仍然收益匪浅,而且随着对这个复杂语言了解的深入和实践项目经验的增加,很多东西和作者产生了一种共鸣,以前种种疑惑突然有种拨云雾而见天日.豁然开朗的感觉,也难怪被列为合格C++程序员之必读书

  • 剖析C++的面向对象编程思想

    面向对象的程序设计 面向对象编程(Object Oriented Programming,OOP,面向对象程序设计) 的主要思想是把构成问题的各个事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙一个事物在整个解决问题的步骤中的行为. 面向过程就是分析出解决问题所需要的步骤,然后用函数逐步实现,再依次调用就可以了. 面向对象和面向过程是两种不同的编程思想,没有哪一种绝对完美,要根据具体需求拟定开发方案.例如,开发一个小型软件或应用程序,工程量小,短时间内即可完成,完全可以采用面

  • Java语言面向对象编程思想之类与对象实例详解

    在初学者学Java的时候,面向对象很难让人搞懂,那么今天小编就来为大家把这个思想来为大家用极为简单的方法理解吧. 首先我们来简单的阐述面向对象的思想. 面向对象: 官方的语言很抽象,我们把官方的解释和定义抛开.想想,自己有什么,对!!我们自己有手脚眼口鼻等一系列的器官.来把自己所具有的器官就可以看作我们的属性,自己是不是可以喜怒哀乐和嬉笑怒骂,这些是不是我们的行为,那么自己的具有的属性加自己有的行为就称为一个对象. 注意!!我们自己,一个个体是一个对象,因为,你是你,我是我,我们虽然有相同的,但

  • 全方位讲解Java的面向对象编程思想

    什么是面向对象? Object 对象,Oriendted 以-为导向的, Programming 程序设计 面向对象就是使用对象进行程序设计,简写成OOP. SP和OOP对比 面向对象的三大原则      封装  继承   多态 对象 对象是面向对象编程的核心部分,是实际存在的具体实体,具有明确定义的状态和行为: 对象其实就是"数据"和"函数"的封装体,其中: 数据表示自身的状态,也称作"属性"或"成员数据": 函数表示自身的

  • Java面向对象编程(封装/继承/多态)实例解析

    本文主要介绍了面向对象的三大特征实例解析,下面看看具体内容. 封装 封装一个Teacher和Student类 package com.hz.test; public class Teacher { private String name; private String majorDirection; private String teachCourse; private int teachAge; public Teacher() { super(); } public Teacher(Stri

  • JavaScript面向对象编程小游戏---贪吃蛇代码实例

    1 面向对象编程思想在程序项目中有着非常明显的优势: 1- 1 代码可读性高.由于继承的存在,即使改变需求,那么维护也只是在局部模块 1-2 维护非常方便并且成本较低. ​2 这个demo是采用了面向对象的编程思想. 用JavaScript 语言编写的游戏小程序--贪吃蛇. ​ 代码注释详细,逻辑清晰 . 非常适合新手前端开发者, 锻炼JavaScript语言的面向对象的编程思想.  该小Demo已上传GitHub,欢迎下载!  觉得好的话,随手给个star,  您的star是我最大的动力! h

  • python面向对象编程设计原则之单一职责原则详解

    目录 一,封装 (一)什么是封装 (二)封装与访问 (三)私有化与访问控制 1,属性与方法的私有化 2,变量名压缩 3,方法重载 (四)属性引用:getter.setter与property 二,单一职责原则 (一)一个不满足单一职责原则的例子 (二)单一职责原则 三,封装与单一职责原则 总结 一,封装 封装是面向对象编程思想的重要特征之一. (一)什么是封装 封装是一个抽象对象的过程,它容纳了对象的属性和行为实现细节,并以此对外提供公共访问. 这样做有几个好处: 分离使用与实现.可直接使用公共

  • 面向对象的编程思想在javascript中的运用上部

    其实,面向对象的思想是独立于编程语言的,例如在C#中,在一个静态类的静态方法中,按照过程式开发调用一系列静态函数,我们很难说这是面向对象的编程,相反,象jquery和extjs这样优秀的javascript库,却处处体现着面向对象的设计思想.本文不打算探讨javascript是否能够算做面向对象的编程语言,这个问题是重视中国式考试的人应该关注的,我这里只是简单的说明如何在javascript中使用面向对象的编程思想. 面向对象首先要有对象.在javascript中创建一个对象非常简单: 复制代码

  • 深入剖析JavaScript面向对象编程

    二. Javascript 面向对象编程:构造函数的继承 本节主要介绍,如何生成一个"继承"多个对象的实例. 比如,现在有一个"动物"对象的构造函数, function Animal(){ this.species = "动物"; } 还有一个"猫"对象的构造函数, function Cat(name,color){ this.name = name; this.color = color; } 怎样才能使"猫&qu

  • 浅谈Python面向对象编程oop思想心得

    花了几个小时给小表弟普及了一下OOP的知识,索性总结一下写篇文章. OOP全称Object Oriented Programming 即面向对象编程,之所以有这么一个奇怪的称呼,是因为这个概念并非凭空而来,而是相对于"面向过程编程"的称呼. 而要了解什么是面向过程,就要从最早的即非面向对象,又非面向过程的原始编程说起. 上古时期 在最早的编程的上古时期,程序都只是简单地顺序执行: print("dosometing") a=int(input()) b=int(in

  • 浅谈Javascript面向对象编程

    在JS中充分使用面向对象设计思想,可以极大限度的提升代码重用.降低模块间的偶合.更好的逻辑分层与并行开发.下面分几个步骤简单谈下我的理解. 一.数据类型与包装类 包装类 -- 类型名 -- 常见值 -- 分类 Number -- number -- 123.123 -- 基本数据类型 Boolean -- Boolean -- true.false -- 基本数据类型 String -- string -- "hello world!" -- 基本数据类型 Object -- obje

随机推荐