第10章 对象和类

<c++ primer plus>第六版

10 对象和类

重要的OOP特性:

  1. 抽象
  2. 封装和数据隐藏
  3. 多态
  4. 继承
  5. 代码的可重用性

10.1 过程性编程和面向对象编程

10.2 抽象和类

10.2.1 类型是什么

10.2.2 c++中的类

#ifndef STOCK00_H_
#define STOCK00_H_

#include <string>

class Stock //类声明
{
private:
    std::string company;
    long shares;
    double share_val;
    double total_val;
    void set_tot()
    {
        total_val = share * share_val;
    }

public:
    void acquire(const std::string & co, long n, double pr);
    void buy(long num, double price);
    void sell(long num, double price);
    void update(double price);
    void show();
}; //最后有一个分号.

#endif

10.3 类的构造函数和析构函数

10.3.1 声明和定义构造函数

class Stock
{};

//构造函数原型
Stock(const string &co, long n=0, double pr=0.0);

//构造函数定义
Stock::Stock(const string &co, long n, double pr)
{
    compary = co; //注意co是参数名, compary是成员名, 它们不能相同, 解决方法1) 成员名加m_前缀, 2) 成员名加_后缀.
    ...
}

10.3.2 使用构造函数

两种方法调用构造函数, 是等价的:

  1. 显式调用: Stock grament = Stock("Furry Mason", 50, 2.5);
  2. 隐式调用: Stock garment("Furry Mason", 50, 2.5); //这种方法更紧凑.

构造函数与new 一起使用

Sock *pstock = new Stock("Electroshock Games", 18, 19.0); //初化一个对象后, 将对象地址赋值给指针.

注意: 不能通过对象来调用构造函数.

10.3.3 默认构造函数

Stock fluffy_the_cat; //未提供显式初始值时, 使用默认构造函数

定义默认构造函数的方式有两种:

  1. 给已有构造函数的所有参数提供默认值.
  2. 通过函数重载来定义另一个构造函数.

10.3.4 析构函数

析构函数完成清理工作.

//析构函数原型
~Stock();

//析构函数定义
Stock::~Stock()
{
}

10.3.5 改进Stock类

头文件stock10.h

//头文件, 声明类, 类成员, 类方法原型
#ifndef STOCK10_H_
#define STOCK10_H_

#include<string>

class Stock
{
private:
    std::string company;
    long shares;
    double share_val;
    double total_val;
    void set_tot()
    {
        total_val = shares * share_val;
    }

public:
    Stock(); //默认构造函数
    Stock(const std::string &co, long n=0, double pr=0.0); //带参数的构造函数
    ~Stock(); //析构函数

    void buy(long num, double price);
    void sell(long num, double price);
    void update(double price);
    void show();
};

#endif

//实现文件, stock10.cpp

// 实现类方法
#include <iostream>
#include "stock10.h" //双引号表示在源文件所在目录搜索它

//实现 默认构造函数
Stock::Stock()
{
    std::cout << "Default constructor called\n";

    company = "no name";
    shares = 0;
    share_val = 0.0;
    total_val = 0.0;
}
//
//实现 带参数的构造函数
Stock::Stock(const std::string & co, long n, double pr)
{
    std::cout << "Constructor using " << co << " called\n";

    company = co;
    if (n<0)
    {
        std::cout << "Number of share cannot be negative; " << company << " shares set to 0.\n";
        shares = 0;
    }
    else
    {
        shares = n;
    }

    share_val = pr;
    set_tot();
}

Stock::~Stock()
{
    std::cout << "Bye, " << company << std::endl;
}

void Stock::show()
{
    using std::cout;
    using std::endl;
    using std::ios_base;

    ios_base::fmtflags orig = cout.setf(ios_base::fixed, ios_base::floatfield);
    std::streamsize prec = cout.precision(3);

    cout << "Company    : " << company << endl;
    cout << "Shares     : " << shares << endl;
    cout << "Share Price: $" << share_val << endl;

    cout.precision(2);
    cout << "Total Worth: $" << total_val << endl;

    cout.setf(orig, ios_base::floatfield);
    cout.precision(prec);
}

//客户文件

#include <iostream>
#include "stock10.h"

int main()
{
    using std::cout;

    cout << "Using constructors to create new objects\n";
    Stock stock1("NanoSmart", 12, 20.0);
    stock1.show();

    return 0;
}

//run文件

g++ stock10.cpp usestock.cpp -o usestock.exe
usestock.exe

注意: 如下两条语句有根本性差别,

第一条语句是初始化, 创建有指定值的对象, 这种效率更高.
Stock stock2 = Stock("Boffo Object", 2, 2.0);

第二条语句是赋值, 相当于创建一个临时对象然后赋值给stock1
stock1 = Stock("Nifty Foods", 10, 50.0);


c++11列表初始化

//使用构造函数 Stock::Stock(const std::string & co, long n=0, double pr=0.0)
Stock hot_tip = {"Derivatives Plus", 100, 45.0};

//使用构造函数 同上, 区别是后两个参数使用默认值.
Stock jock {"Sport Age Storage, Inc"};

//使用默认构造函数.
Stock temp {};

const成员函数

如果一个对象被声明为常对象, 则它只能调用常成员函数(不能修改类成员的函数)

常成员函数声明: void show() const; //注意const在后面
常成员函数定义: void Stock::show() const {};//注意const在后面
常成员函数调用: const Stock land = Stock("XX"); land.show();

10.4 this指针

this是一个指针, 指向调用当前成员函数的对象.

10.5 对象数组

Stock mystuff [4]; //创建一个数组, 包含4个Stock对象

Stock stocks[4] = {
    Stock("0", 0, 0.0),
    Stock("1", 1, 1.0),
    Stock("2", 2, 2.0),
    Stock("3", 3, 3.0),
    Stock()
};

this->member

10.6 类作用域

前面提到的作用域:
全局作用域->文件作用域
局部作用域->代码块作用域

在类中定义的名称(类变量和类方法)的作用域为整个类. 在类外不可见.
调用类的函数只能通过对象.

使类成员名时, 根据上下文有三种方法:
1). 直接成员运算符(.)
2). 间接成员运算符(->)
3). 域解析运算符(:😃

10.6.1 作用域为类的常量

c++在类中定义常量的方式: 1) 使用枚举, 2)使用关键字static.

class Bakery
{
private:
    static const int Months = 12; //类常量, 不存储在对象中.
    double costs[Months];
}

10.6.1 作用域内枚举

10.7 抽象数据类型

posted @ 2022-07-10 11:14  编程驴子  阅读(39)  评论(0编辑  收藏  举报