第十章 对象和类

本文详细介绍了面向对象编程的核心概念,包括抽象、封装、数据隐藏、多态和继承。强调了类的声明和实现,以及访问控制的重要性。讨论了构造函数和析构函数的作用,并解释了如何通过const成员函数确保对象的只读性。同时,提到了枚举在编程中的应用。
摘要由CSDN通过智能技术生成

OPP特性:抽象、封装和数据隐藏、多态、继承、代码的可重用性

抽象和类

将问题的本质抽象出来,并根据特征来描述解决方案。

类规范有两部分组成:

1 类声明:以数据成员的方式描述数据部分,以成员函数(方法)的方式描述公有接口。

2 类方法定义:描述如何实现类成员函数。

类声明提供了类的蓝图,方法定义则提供了细节。

接口: 接口是一个共享框架;对于类,我们说公共接口,公共(Public)是使用类的程序,交互系统由类对象组成,接口由编写类的人提供的方法组成。接口让程序员能够编写与类对象交互的代码让程序能使用类对象。

C++中通常将接口(类定义)的定义放在头文件中,并将实现(类的方法的代码)放在原文件中,

访问控制:public 和private描述了对类成员的访问控制,程序可以访问对象的公有部分,只能通过公共部分(或者友元函数)访问对象的私有成员。防止程序直接访问数据,被称为数据隐藏。

关键字protected被用在类继承时,后边讨论。

类的设计应尽可能的将公有接口与类的实现细节分开,公有接口表示设计的抽象组件。将实现细节放在一起并将他们与抽象分开被称为封装。数据隐藏(将数据放在私有部分)是一种封装。将实现细节隐藏在私有部分(私有函数),也是一种封装。封装的另一个例子是,将类函数定义和声明放在不同的文件中。

Private可以省略,类中,成员默认是私有的,只有在public中的才是共有,对外接口。注意结构体默认是public的。

类成员函数:

两个特殊特征:使用作用域解析符(::)标记成员函数;类的方法可以访问private组件

void stock::update(doule price);

内联函数:

定义位于类声明中的函数将自动成为内联函数,短小的成员函数可以作为内联函数。

类声明之外也可以显式的定义函数未内联函数, 使用关键字inline

inline void Stock::set_tot(){
    ... 
}

联函数要求在每个使用它的文件中都要对其进行定义所以最简单方法是内联函数放在定义类的头文件中。

每个对象都有自己的内存空间,保存着自己的内部变量和类成员。同一个类的所有对象共享类方法,每种方法只有一个副本。不同的对象的相同方法执行同一个代码块,只是将这些代码用于不同的数据。

#ifndef __SLT_ENG_H__
#define __SLT_ENG_H__

void start_slt_eng();
class Capital {
    private:
        int my_total_funds;

    public:
        Capital();
        void store(int funds);
        void spend(int funds);
        void show();
        ~Capital();
};
#endif //SLT_ENG
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include "slt_eng.h"

using namespace std;

void start_slt_eng() {
    printf("start_slt_eng!\n");
    Capital mycapital(300, "zhangsan");
    mycapital.show();
    mycapital.store(100);
    mycapital.show();
    mycapital.spend(20);
    cout << "end spend" <<endl;
    cout << "mycapital" << &mycapital <<endl;
    Capital *licapital = new Capital(200, "wangwu");
    licapital->show();
    licapital->store(100);
    licapital->show();
    cout << "spend 30" <<endl;
    licapital->spend(30);
    cout << "mycapital" << licapital <<endl;
    delete licapital;
}

Capital::Capital() {
    cout << "gouzao: Capital"<< endl;
    my_total_funds = 0;
}

Capital::Capital(int funds, const char* name) {
    cout << "gouzao: Capital"<< endl;
    my_total_funds = funds;
    this->name = name;
}

void Capital::show() {
    cout << name << " funds:" << my_total_funds << endl;
}

void Capital::spend(int funds) {
    cout << name << " before spend my_total_funds:" << my_total_funds << endl;
    my_total_funds -= funds;
    cout << name << " after spend my_total_funds:" << my_total_funds << endl;
}

void Capital::store(int funds) {
    cout << name << " before store my_total_funds:" << my_total_funds << endl;
    my_total_funds += funds;
    cout << name << " after store my_total_funds:" << my_total_funds << endl;
}

Capital::~Capital() {
    cout << "xigou: Capital :"<< this << endl;
    my_total_funds = 0;
}
输出结果:
start_slt_eng!
gouzao: Capital
my_total_funds:0
before store my_total_funds:0
after store my_total_funds:100
my_total_funds:100
before spend my_total_funds:100
after spend my_total_funds:80
end spend
mycapital0x62fd00
gouzao: Capital
licapital
my_total_funds:0
before store my_total_funds:0
after store my_total_funds:100
my_total_funds:100
licapital spend 30
before spend my_total_funds:100
after spend my_total_funds:70
mycapital0x3522f80
xigou: Capital :0x3522f80
xigou: Capital :0x62fd00
end main 

OOP的设计常遵从客户/服务器模型,服务器即类的声明与定义,客户端就是实现类的程序。

服务端不应该修改Public接口,修改内部实现对客户端不会产生影响。

构造函数和析构函数

构造函数目的是让使用类对象像使用标准的类型一样,

int age = 20;
struct st_student {
    char name[20];
    int age;
    int high;
  };

  struct st_student stu1 = {"zhangsan", 10, 168};
  struct st_student stu2 = {"lisi", 17, 178};
  struct st_student stu3 = {"wangwu", 18, 188};

    class st_student {
    public:             //内部变量如果是public的就可以像struct一样用初始化列表{}初始化
        char name[20];
        int age;
        int high;
  };

   st_student stu1 = {"zhangsan", 10, 168}; // 编译器按照列表位置进行初始化,例如10 对应第二个变量age
   st_student stu2 = {"lisi", 17, 178};
   st_student stu3{
     "wangwu",
   18,
   188
  };

不能像常规变量那样初始化的原因就是类中变量是private的,外部无法访问,如果声明为public,就可以了。struct可以的原因就是结构体默认变量类型为public。

所以构造函数必须是public的,值得注意的是构造函数没有返回类型

Capital::Capital(int funds, const char* name);

可以使用默认参数:

Capital::Capital(int funds, const char* name = "defaultName");

构造函数的参数,不能和类成员变量名相同,可以参考下边写法。

Capital::Capital(int funds, const char* name) {
    cout << "gouzao: Capital"<< endl;
    m_my_total_funds = funds;
    m_name = name;
}

Capital::Capital(int funds, const char* name) {
    cout << "gouzao: Capital"<< endl;
    my_total_funds_ = funds;
    name_ = name;
}

构造函数的使用

显示使用:

Capital mycap = Capital(100, "zhangsan");

隐式使用

Capital myCapital(100, "zhangsan");

Capital *pmyCapital = new Capital(100, "zhangsan");

默认构造函数

默认构造函数是在未显式初始值时使用的构造函数:例如:Capital myCapital;

值的注意的是只有当没有构造函数时候,编译器才会自动生成默认构造函数,当有任何一个构造函数时候,需要显式写出构造函数:

Capital capital1; 此种定义才是使用默认构造函数,

Capital capital1();这种写法是错误的,不能实例化对象。是一个函数声明。

Capital::Capital() {
    cout << "moren gouzao: Capital"<< endl;
    my_total_funds = 0;
}

也可以将所有参数设置默认值
Capital::Capital(int funds = 100, const char* name = "defaultName") {
    cout << "gouzao: Capital"<< endl;
    m_my_total_funds = funds;
    m_name = name;
}

析构函数:

析构函数没有参数(不需要参数,只是用来回收数据),声明原型为: ~Capital();// 和类名相同。

Capital capital1 = Capital(200, "wowowowo"); // 此种定义不会创建临时对象(可能有些编译器会),而是直接初始化capital1;

capital2 = Capital(200, "wowowowo");此种写法会创建一个临时对象,然后赋值给capital2,之后程序会立即自动调用析构函数。

capital1 = capital2;说明对象间可以像普通变量一样相互赋值。

默认情况下,将一个对象赋值给另一个对象,C++会将对象capital2中所有数据成员变量复制到capital1中。

const成员函数

const Capital mycapital = Capital(200, "wowowowo");// 此定义是定义mycapital为const型,说明mycapital不能被修改,是只读的。

所以调用 mycapital.show();是不合法的,因为不能保证函数show()不会修改对象成员,所以C++使用const成员函数解决此问题:

void show() const; //声明函数show() 为const,说明此函数不能修改类成员变量
void show() const { //定义函数show() 为const,说明此函数不能修改类成员变量
    ...
}

编程规则:如果函数不会修改类成员变量,应尽可能的声明函数为 const成员函数

注意:c中普通函数防止修改参数,是在参数列表中声明参数为const。

作用域内枚举:

enum class egg {small, medium, jumbo}

使用: rgg choice = egg:: small;

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值