面向对象编程学习笔记(C++)

参考书:c/c++程序设计教程,龚沛增、杨志强 主编
本文主要内容架构如下图:


面向对象(c++)

1 概述

面向对象编程(Object Oriented Programming),面向对象的思想就是要面对现实世界的实体,以对象为基本单位,分析、设计和实现一个系统。
基本概念:

  1. 对象
    现实世界中的对象是各种各样的实体,可以是具体的或抽象的事物。每个对象皆有自己的特征、行为和作用在该对象上的活动。

  2. 许多对象具有相似的性质,执行相同的操作,称之为一类对象。类是创建对象的模板,对象则是类的实例。
  3. 消息
    在面向对象的程序中,程序执行是对象之间传递消息完成的,消息传递一般由 接收消息的对象、所要触发的方法和执行此方法需要的参数组成的。
  4. 方法
    方法是某个对象接受了消息后采取的一系列操作的描述。

2 类和对象

本节内容如下:


类和对象

2.1 类的定义

类定义的一般形式如下:

class 类名
  {
    public :
      成员函数或数据的说明;
    private :
      成员函数或数据的说明;
    protected :
      成员函数或数据的说明;
  };
  各成员函数的实现;

--类的定义包括说明和实现两部分。如果成员函数在说明部分已经给出定义,则在实现部分可以省略;
--类的成员包含数据成员和函数成员,自身类的对象不能作为自己的成员;
--private,public,protected规定了成员如何被访问,缺省时为private;
--不涉及继承时,protected 与private用法相同;
--类的数据成员不能在声明时进行初始化,只能通过成员函数实现;
--在类体外定义成员函数时,格式为:

类名::函数名(参数)
{
  函数实现
};

2.2 对象的定义

定义对象
类名 对象名;
如:

class staff  {......};
 staff s,*p,s1[5];
//staff为已经定义的类,s是一个对象,p是指向对象的指针,s1为对象数组

对象的访问

  1. 一般对象成员:
    对象名.数据成员名
    对象名.函数成员名(参数)
  2. 指针对象成员:
    对象指针->数据成员
    对象指针->函数成员(参数)

    对象指针).数据成员
    对象指针).函数成员(参数)

2.3 对象初始化

  1. 构造函数
    --与类名相同,不指定函数类型;
    --属于成员函数,可以在类体内或体外实现;
    --可以重载;
    --在创建对象时自动调用,不能在程序中直接调用,多用于初始化;
    --用户未定义时,系统会自动生成缺省构造函数;
    --用户定义了构造函数,系统不会生成缺省构造函数;
    --若定义一个静态对象而没有初始化时,编译器会将所有数据成员初始化为0.

  2. 析构函数
    --在程序结束或使用对象的函数结束前会自动调用,用于释放对象;
    --析构函数名是在类名前加~,无参数,不需指定类型;
    --属于成员函数,可以在类体内或体外定义;
    --不能重载;
    --可以由系统自动调用,也可以在程序中调用;
    --用户未定义时,系统会自动生成空的缺省析构函数。

  3. 拷贝初始化构造函数
    --用一个已知的对象来初始化一个被创建的同类对象;
    --函数名与类名相同,只有一个参数,且该参数是对同类对象的引用;
    --如果用户没有定义拷贝初始化构造函数,则系统会自动生成,并将参数对象的全部数据值拷贝给正在创建的对象。

2.4 常对象和常成员

声明常对象:

const 类名 对象名;

常对象中所有数据成员的值只能在构造函数中初始化,不能被修改。

常函数成员
声明常函数成员:

类型说明符 函数名(参数) const
{......};

--只有常成员函数可以操作常对象;
--修改数据对象的函数不能声明为常函数;

常数据成员
声明常数据成员:

const 数据类型 变量名;

--常数据成员不能被任何函数改动;
--构造函数只能通过初始化列表对其初始化,如:

class circle
{
  private:
    double x,y;
    const double r;
  public:
    circle(double x1, double y1,double r1):r(re)
      {
        x=x1;y=y1;
      }
 }

2.5 静态成员

希望一个成员能供所有对象共享时,可以设为静态成员。
静态数据成员
--静态数据成员声明时在前面加static;
--静态数据成员是类的成员,不是对象的成员;
--初始化在类体外进行,不加static和访问权限控制符。

//初始化格式:
数据类型  类名::静态数据成员=值;
//引用格式:
类名:静态数据成员名

静态函数成员
--声明时在前面加static;
--静态成员函数中可以直接引用静态数据成员,对于非静态数据成员,要通过对象引用;
--除了可以像其他成员函数一样引用,还可以如下引用:

类名::成员函数名(参数)

2.6 友元函数

友元函数提供了一种非成员函数访问类的私有成员的方法,在一定情况下可以提高程序的执行效率,但破坏了类的封装和隐藏性。
--友元函数不是成员函数,但要在类体内说明;
--友元函数说明时,要在前面加friend,实现时不许加friend;
--友元函数可以通过对象的方式访问类中的私有成员。

3 派生和继承

继承是软件可重用性的一种形式,新类通过这种方式,从现有的类中吸收其属性和行为,并对其覆盖和改写,产生新类所需要的功能。
本节内容如下:


继承和派生

3.1 派生

通过继承机制,可以应用现有类来定义新类。已经存在的类称为基类或父类,由已存在的类派生的新类叫派生类或子类。
派生类拥有基类的成员,也可以定义新成员。

3.2 继承

一个派生类可以由一个基类派生,称为单继承;也可以由多个基类派生,称为多继承。
单继承

  1. 派生类的定义

     class 派生类名:继承方式  基类名
     {
       派生类新成员定义
     };
    
  2. 派生类的继承方式
    不同的继承方式中,派生类对基类成员的访问权限不同,如下:

基类 私有成员 公有成员 保护成员
私有派生 不可访问 私有成员 私有成员
公有派生 不可访问 公有成员 保护成员
保护派生 不可访问 保护成员 保护成员

--不论何种继承方式,基类的私有成员均不可被派生类及其成员函数访问;
--私有继承时,基类的公有成员和保护成员均成为派生类的私有成员;
--公有继承时,基类的公有成员和保护成员类型不变被继承到派生类中;
--保护继承时,基类的公有成员和保护成员均成为基类的保护成员;
--若基类的公用成员访问了基类的私有成员,则在派生类中不能使用,需要通过基类的方式调用。

  1. 派生类的构造函数
    定义派生类的构造函数时,除了对自己的数据成员初始化,还需调用基类的构造函数。如果派生类中的成员含有基类对象,则还应该对基类对象进行初始化,例如:

     派生类构造函数(初始化总参数表):基类构造函数(参数表1),基类对象名(参数表2)
     {
       派生类中数据成员初始化
     }
    

--调用顺序:基类构造函数——基类对象构造函数——派生类构造函数;
--基类中有缺省的构造函数或未定义时,派生类构造函数可以省略调用基类构造函数;
--若基类只包含有参数的构造函数,则在派生类中一定要调用。

#include 
using   namespace   std   ;
class circle
{
  private:
    double x,y,r;
  public:
    void print() //const
    {
        cout<<"圆心:"<

运行结果:


image.png
  1. 派生类析构函数
    格式:

     ~派生类名()
     {......};
    

系统先执行派生类的析构函数,再执行基类的析构函数。

4 多态性

多态性是指同一个操作对于不同的对象会产生不同的反应。函数重载和运算符重载属于静态重载,建立在虚函数上的多态性属于动态重载。
本节内容如下:


多态性

4.1 函数重载

函数重载是指同一个函数名有不同的定义,定义重载函数时,要求参数至少有一个类型不同,或者个数不同,对返回值无要求。

4.2 运算符重载

  1. 运算符重载原则
    遵循函数重载的原则;
    不能改变运算符的优先级和结合性,不改变其语法结构。

  2. 重载为类的成员函数
    定义形式:
    类名 operetor 运算符(参数表)
    调用形式:
    对象1 运算符 对象2
    例如(程序待完善):

     class Str    
     {
       private:
         char *s;
       ......
       public:
         Str operator + (Str s1)
         //将+号重载为字符串拼接
         {
           strcat(s, s1.s);
           Str result(s);
           return result;
         }
     };
     void main()
     {
       Str s1,s2,s3;
       s3=s1+s2;
     }
    
  3. 重载为友元函数
    (待补充)

  4. this指针
    this是一个无需特殊定义的指针,它隐含于每一个类的成员函数中,指向正在被某个成员函数操作的对象。
    如果某个对象调用的成员函数,则编译程序首先将这个对象的地址赋给this指针,然后调用成员函数。

4.3 虚函数

虚函数是一种非静态的成员函数,反映了基类和派生类之间的特殊关系,定义形式:

virtual 类型说明符 函数名 (参数表)

如果在基类中,某个函数被声明为虚函数,则在派生类中,该成员函数可能有其他的实现方法。
例子:

class Animal
{
public:
    void character()
    {
        cout<<"动物特征:不同"<

运行结果:


image.png

在例程中,函数f的参数为基类指针,主函数调用时传入的为派生类的地址,此时,实际操作的是基类的成员函数,而对于虚函数,则会根据派生类对象的地址执行派生类中的函数。
虚函数的使用说明:
--派生类中的虚函数应与基类中的虚函数有相同的函数名、参数类型及个数;
--派生类的虚函数可以不显示声明;
--只有虚函数操作的是对象的指针或对象的引用时,对该虚函数的调用采取的才是动态联编。

4.4 抽象类

含有纯虚函数的类称为抽象类。
纯虚函数是指在基类中定义为空的虚函数。
抽象类的性质:
--只能用作其他类的基类,不能建立其对象;
--不能用作参数类型和函数返回值类型;
--可以说明指向抽象类指针引用,此指针可以指向其派生类。

你可能感兴趣的:(面向对象编程学习笔记(C++))