C++第十章 对象和类

第十章 对象和类

本章内容包括:
  • 定义与实现类
  • 使用类
  • 对象数组
  • 作用域为类的常量
  • 作用域内枚举
  • 抽象数据类型

类规范由两个部分组成:

  • 类声明:以数据成员的方式描述数据部分,以成员函数的方式描述公有接口。
  • 类方法定义:描述如何实现成员函数
定义与实现类:

stack00.h

#ifndef D1_STOCK00_H
#define D1_STOCK00_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:
    void buy(long num, double price);

    void sell(long num, double price);

    void update(double price);

    void show() const;

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

    Stock(const std::string &co, long n, double pr); // 构造
    
    Stock();// 构造
    
    ~Stock();// 析构
};

#endif //D1_STOCK00_H

stock00.cpp

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

Stock::Stock(const std::string &co, long n = 0, double pr = 0.0) {
    this->_company = co;
    if (n < 0) {
        std::cout << "Number of shares can‘t be Negative; "
                  << _company << " shares set to be 0.\n";
        this->_shares = 0;
    } else {
        this->_shares = n;
    }
    this->_share_val = pr;
    set_tot();
}
Stock::Stock() {
    this->_company = "";
    this->_shares = 0;
    this->_share_val = 0.0;
    this-> _total_val = 0.0;
}

Stock::~Stock() {
    std::cout << "bye, " << _company << '\n';
}

void Stock::buy(long num, double price) {
    if (num < 0) {
        std::cout << "Number of num can‘t be Negative; "
                  << "Transaction is aborted\n";
    } else {
        _shares += num;
        _share_val = price;
        set_tot();
    }
}

void Stock::sell(long num, double price) {
    if (num < 0) {
        std::cout << "Number of num can‘t be Negative; "
                  << "Transaction is aborted.\n";
    } else if (num > _shares) {
        std::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() const{
    std::cout << "Company: " << _company
              << " Shares: " << _shares << '\n'
              << " Share Price: $" << _share_val
              << " Total Worth: $" << _total_val << '\n';
}

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

}

定义于类声明中的函数都自动成为内联函数,因此Stock::set_tot()是一个内联函数

使用类:

main.cpp

#include <iostream>
#include "classes/stock00.h"

int main(int argnum, char *args[]) {
    Stock fluffy("NanoSmart", 20, 12.50);
    fluffy.show();
    fluffy.buy(15, 18.25);
    fluffy.show();
    fluffy.sell(400, 20.00);
    fluffy.show();
    fluffy.buy(30000, 40.125);
    fluffy.show();
    fluffy.sell(400000, 12.5);
    fluffy.show();
    return 0;
}

可以将成员函数定义为 void show() const 来保证成员变量不被修改

对象数组:
#include <iostream>
#include "classes/stock00.h"

int main(int argnum, char *args[]) {
    Stock mystuff[4];
    mystuff[1].show();
    return 0;
}
结果
Company:  Shares: 0
 Share Price: $0 Total Worth: $0
bye, 
bye, 
bye, 
bye, 
作用域为类的常量:

有时,使符号常量的作用域为类很有必要。例如,类声明可能使用字面值30来指定数组的长度,由于该常量对于所有对象来说都是相同的,因此创建一个由所有对象共享的常量是个很不错的主意,但,这样是不行的:

class Bakert{
private:
    const int Months = 12;
    double const[Months];
};

因为,声明类只是描述了对象的形式,并没有创建对象。因此,创建对象前,将没有用于储存值的空间。有两种方式可以实现这个目标,并且效果相同

  • 第一种是在类中声明一个枚举。在类中声明的枚举作用域为整个类,因此可以用枚举为整型常量提供作用域为类的符号名称。

    class Bakert{
    private:
        enum {Months=12};
        double cons[Months];
    };
    

    用这种方式声明枚举并不会创建类数据成员。也就说,所有对象中都不包含枚举。另外,Months只是一个符号名称,编译器用12代替

  • 使用关键字static;

    class Bakert{
    private:
        static const int Months= 12;
        double cons[Months];
    };
    

    这将创建一个名为Months的常量,该常量与其他静态变量存储在一起,而不是存储在对象中。因此,只有一个Months常量,被所有Bakery对象共享。

作用域内枚举:

传统的枚举可能存在一些问题,其中之一是两个枚举定义中的枚举量可能发生冲突:

enum egg {Small, Medium, Large, Jumbo};
enum t_shirt {Small, Medium, Large, Xlarge};

这这将无法编译。C++11中提供了一种新枚举,其枚举常量的作用域为类:

enum class egg {Small, Medium, Large, Jumbo};
enum class t_shirt {Small, Medium, Large, Xlarge};

egg choice = egg::Large
t_shirt Floyd = t_shirt::Large

c++11 中还提高了作用域内枚举的类型安全。有些情况下,常规枚举将自动转换成为整数,如将其赋值给其他int变量或表达式时。 但是作用域内枚举不能隐式转换

int main(int argnum, char *args[]) {
    enum egg_old {Small, Medium, Large, Jumbo};
    enum class t_shirt {Small, Medium, Large, Xlarge};

    egg_old one = Medium;
    t_shirt rolf = t_shirt ::Large;
    int king = one;
//    int ring = rolf;  not allowed
    if (king < Jumbo){
        std::cout << "Jumbo converted to be int;\n";
    }
//    if (king < t_shirt::Xlarge) error not allowed
    return 0;
}

但必要时,可显式转换

int Frodo = int(t_shirt::Medium);

枚举用某种底层整型表示,C++98中,如何选择取决于实现,因此包含枚举的结构的长度可能随系统而异。对于作用域内枚举,C++11中消除了这种依赖。默认情况下,C++11作用域内枚举的底层类型为int。另外,还提供了一种语法,可用于不同选择

enum class : short pizza {Small, Medium, Large, Xlarge}
抽象数据类型:

栈:stacktp.h

#ifndef D1_STACKTP_H
#define D1_STACKTP_H
template <class Type>
class Stack
{
private:
    enum {Max= 10};
    Type items[Max];
    int _top;
public:
    Stack();
    explicit Stack(int top);
    bool isempty();
    bool push(const Type &item);
};

template <class Type>
Stack<Type>::Stack() {
    _top = 0;
}

template <class Type>
Stack<Type>::Stack(int top) {
    _top = top;
}


template<class Type>
bool Stack<Type>::isempty() {
    return false;
}

template<class Type>
bool Stack<Type>::push(const Type &item) {
    return false;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值