C++ primer plus 学习笔记(第10章)

本文深入探讨C++中类与对象的概念,包括抽象、类型、构造函数、析构函数和this指针的使用。通过具体示例,阐述了如何定义和实现类,以及如何在程序中使用类对象。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第10章 对象和类
10.2 抽象和类
接口描述了用户如何初始化、更新和显示数据
C++中,用户定义类型指的是实现抽象接口的类设计

10.2.1 类型
指定基本类型完成以下工作:
决定数据对象需要的内存数量;
决定如何解释内存中的位;
决定可使用数据对象执行的操作或方法;

10.2.2 C++中的类
1.类是一种将抽象转换为用户定义类型的C++工具,它将数据表示和操纵数据的方法合成一个包。
2.接下来定义类,类规范由两个部分组成:
类声明:以数据成员的方式描述数据部分,以成员函数(或方法)的方式描述公有接口。
类方法定义:描述如何实现类成员函数
3. C++中将接口(类定义)放在头文件中,并将实现(类方法的代码)放在源代码文件中。
首先看一下类定义

//stock00.h
#ifndef STOCK00_H_
#define STOCK00_H_
#include <string>
class Stock     //class declaration
{
private:
    std::string company;
    long shares;
    double share_val;
    double total_val;
    void set_tot(){total_val=shares*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();
};  //note semicolon at the end
#endif

代码说明:
关键词class 标识类定义
类名称Stock成为这个用户定义的类型的名称
关键字private标识只能通过公共成员访问的类成员(数据隐藏)
关键字public标识组成类的公共接口的类成员(抽象)
类成员可以是数据类型,也可以是函数
由于隐藏数据是面向对象编程主要的目标之一,因此数据项通常放在私有部分,组成类的接口的成员函数放在公有部分;
公有方法可以使用私有部分中的数据,也可以使用私有成员函数来处理不属于公有接口的实现细节。
不必在类声明中使用关键字private,因为这是类对象的默认访问控制

10.2.3 实现类成员函数
类成员函数具有两个特殊的特征:
定义成员函数时,使用作用域解析运算符(::)来标识函数所属的类;
类方法可以访问类的private组件
成员函数的编写:

// stock00.cpp -- implementing the Stock class
// version 00
#include <iostream>
#include "stock00.h"
void Stock::acquire(const std::string & co, long n, double pr)
{
    company = co;
    if (n < 0)
    {
        std::cout << "Number of shares can't be negative; "
                  << company << " shares set to 0.\n";
        shares = 0;
    }
    else
        shares = n;
    share_val = pr;
    set_tot();
}
void Stock::buy(long num, double price)
{
     if (num < 0)
    {
        std::cout << "Number of shares purchased can't be negative. "
             << "Transaction is aborted.\n";
    }
    else
    {
        shares += num;
        share_val = price;
        set_tot();
    }
}
void Stock::sell(long num, double price)
{
    using std::cout;
    if (num < 0)
    {
        cout << "Number of shares sold can't be negative. "
             << "Transaction is aborted.\n";
    }
    else if (num > shares)
    {
        cout << "You can't sell more than you have! "
             << "Transaction is aborted.\n";
    }
    else
    {
        shares -= num;
        share_val = price;
        set_tot();
    }
}
void Stock::update(double price)
{
    share_val = price;
    set_tot();
}
void Stock::show()
{
    std::cout << "Company: " << company
              << "  Shares: " << shares << '\n'
              << "  Share Price: $" << share_val
              << "  Total Worth: $" << total_val << '\n';
}

10.2.4 使用类
创建并使用类对象

// usestok0.cpp -- the client program
// compile with stock.cpp
#include <iostream>
#include "stock00.h"
int main()
{
    Stock fluffy_the_cat;
    fluffy_the_cat.acquire("NanoSmart", 20, 12.50);
    fluffy_the_cat.show();
    fluffy_the_cat.buy(15, 18.125);
    fluffy_the_cat.show();
    fluffy_the_cat.sell(400, 20.00);
    fluffy_the_cat.show();
    fluffy_the_cat.buy(300000,40.125);
    fluffy_the_cat.show();
    fluffy_the_cat.sell(300000,0.125);
    fluffy_the_cat.show();
    // std::cin.get();
    return 0;
}

10.3 类的构造函数和析构函数
利用类的构造函数对对象进行初始化。

10.3.1 声明和定义构造函数
创建Stock的构造函数。由于需要为Stock对象提供3个值,因此应为构造函数提供3个参数。
一是可以使用默认参数完成:

Stock(const string &co,long n=0,double pr=0.0);

二是利用构造函数定义:

Stock::Stock(const string &co,long n,double pr)
{
company=co;
if (n<0)
 {
  std::cerr<<"Number of Shares can't be negative;"
            <<company<<"shares set to 0.\n";
  shares=0;
 }
 else
    shares=n;
 share_val=pr;
 set_tot();
}

注意:构造函数的参数表示的不是类成员,而是赋给类成员的值。

10.3.2 使用构造函数
C++提供了两种使用构造函数来初始化对象的方法。
第一种是显示地调用构造函数:

Stock food=Stock("world Cabbage",250,1.25);

第二种是隐式地调用构造函数:

Stock garmet("Furry Mason",50,2.5);

下面是将构造函数与new一起使用的方法:

Stock *pstock=new Stock("Electroshock Games",18,19.0);

10.3.4 析构函数
利用构造函数创建对象后,程序负责跟踪该对象。对象过期时,程序将自动调用析构函数完成清理工作。特别是在构造函数使用new分配内存时,析构函数则使用delete来释放内存。当构造函数没有使用new,析构函数实际上没有需要完成的任务。
析构函数没有参数,因此Stock析构函数的原型必须如下:

~Stock();

则Stock的析构函数可以编写为:

Stock::~Stock()
{
}

10.3.5 改写原有code
将构造函数和析构函数加入到类和方法的定义中,则原先的stock00改为stock10
1)头文件

#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();        // default constructor
    Stock(const std::string & co, long n = 0, double pr = 0.0);
    ~Stock();       // noisy destructor
    void buy(long num, double price);
    void sell(long num, double price);
    void update(double price);
    void show();
};
#endif

2)实现文件

// stock1.cpp ?Stock class implementation with constructors, destructor added
#include <iostream>
#include "stock10.h"
// constructors (verbose versions)
Stock::Stock()        // default constructor
{
    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 shares can't be negative; "
                   << company << " shares set to 0.\n";
        shares = 0;
    }
    else
        shares = n;
    share_val = pr;
    set_tot();
}
// class destructor
Stock::~Stock()        // verbose class destructor
{
    std::cout << "Bye, " << company << "!\n";
}
// other methods
void Stock::buy(long num, double price)
{
     if (num < 0)
    {
        std::cout << "Number of shares purchased can't be negative. "
             << "Transaction is aborted.\n";
    }
    else
    {
        shares += num;
        share_val = price;
        set_tot();
    }
}
void Stock::sell(long num, double price)
{
    using std::cout;
    if (num < 0)
    {
        cout << "Number of shares sold can't be negative. "
             << "Transaction is aborted.\n";
    }
    else if (num > shares)
    {
        cout << "You can't sell more than you have! "
             << "Transaction is aborted.\n";
    }
    else
    {
        shares -= num;
        share_val = price;
        set_tot();
    }
}
void Stock::update(double price)
{
    share_val = price;
    set_tot();
}
void Stock::show()
{
    using std::cout;
    using std::ios_base;
    // set format to #.###
    ios_base::fmtflags orig = 
        cout.setf(ios_base::fixed, ios_base::floatfield); 
    std::streamsize prec = cout.precision(3);
    cout << "Company: " << company
        << "  Shares: " << shares << '\n';
    cout << "  Share Price: $" << share_val;
    // set format to #.##
    cout.precision(2);
    cout << "  Total Worth: $" << total_val << '\n';
    // restore original format
    cout.setf(orig, ios_base::floatfield);
    cout.precision(prec);
}

客户文件:

// usestok1.cpp -- using the Stock class
// compile with stock10.cpp
#include <iostream>
#include "stock10.h"
int main()
{
  {
    using std::cout;
    cout << "Using constructors to create new objects\n";
    Stock stock1("NanoSmart", 12, 20.0);            // syntax 1
    stock1.show();
    Stock stock2 = Stock ("Boffo Objects", 2, 2.0); // syntax 2
    stock2.show();
    cout << "Assigning stock1 to stock2:\n";
    stock2 = stock1;
    cout << "Listing stock1 and stock2:\n";
    stock1.show();
    stock2.show();
    cout << "Using a constructor to reset an object\n";
    stock1 = Stock("Nifty Foods", 10, 50.0);    // temp object
    cout << "Revised stock1:\n";
    stock1.show();
    cout << "Done\n";
  }
	// std::cin.get();
    return 0; 
}

10.4 this指针
当类成员函数涉及到两个对象时,在这种情况下需要使用C++的this指针
声明:

const Stock & topval(const Stock & s) const;

成员函数

const Stock & Stock::topval(const Stock & s) const
{
    if (s.total_val > total_val)
        return s;
    else
        return *this; 
}

10.5 对象数组
用户可以创建同一个类的多个对象。声明对象数组的方法与声明标准类型数组相同:
Stock mystuff[4]; //creates an array of 4 Stock objects
当程序创建未被显式初始化的类对象时,总是调用默认构造函数。每个元素(mystuff[0]、mystuff[1]等)但是Stock对象,可以使用Stock方法:

mystuff[0].update();
mystuff[3].show();
const Stock *tops=mystuff[2].topval(mystuff[1]);

可以用构造函数来初始化数组元素。在这种情况下,必须为每个元素调用构造函数:

const int STKS=10;
Stock stocks[STKS]={
    Stock("NA",12.5,20),
    Stock("NA7",12.5,20),
    Stock("PNA",19.5,20),
    Stock("NAU",12.5,201)
};

如果声明只初始化了数组的部分元素,那么余下的元素将使用默认构造函数进行初始化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值