zoukankan      html  css  js  c++  java
  • C++ Primer Plus的若干收获--(九)

    这篇博文我接着上一篇来写,相同讲一些关于类的一些基础知识。

    本篇将会继续使用上篇的股票类STock,这里给出接口

    ifndef STOCKOO_H_
    #define STOCKOO_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(const std::string& co,long n=0,double pr=0.0);
       Stock();    
        void acqure(const std::string&co, long n,double ptr);//获得股票
        void buy(long num,double price);//增持
        void sell(long num,double price);//卖出股票
        void update(double price);//更新股票价格
        void show() const;//显示关于所持的股票信息
    };
    #endif // STOCKOO_H_
    
    

     

    9.1 对象数组

    实际上。声明对象数组的方法与声明标准类型的数组的方法同样:

    Stock mystuff[4];


    前面讲过。当程序创建未被现实初始化的对象数组时,总是调用默认构造函数。上述声明要求,这个类要么没有显式的定义不论什么构造函数(这样的情况下,将使用不运行不论什么操作的隐式默认构造函数),要么定义了一个显式的默认构造函数。每一个元素都是一个Stock对象。

    我们也能够利用多种构造函数来初始化我的对象数组

    const int STK=10;
    Stock stocks[STK]={
       Stock("NAnoSmart",12.5,20),
       Stock(),
       Stock("Monolithis",130,2.5),
    };


    9.2 类作用域

    在类定义的名称的作用于都为整个类,作用域为整个类的名称仅仅在该类中是已知的,在类外是不可知的。因此。能够在不同类中使用同样的类成员名而不会引起冲突。

    比方。Stock类的shares成员不同于JobRide的shares成员。

    另外。类的作用域意味着不能从外部直接訪问类的成员,共同拥有成员函数也是如此。也就是说,要调用公有成员函数。必须通过对象。

    总之,在类声明或成员函数定义中。能够使用维修时的成员名称。构造函数在被调用时,才干被识别,由于它的名称与类名同样。在其它情况下,使用类成员名时,必须依据上下文使用直接成员运算符(.),间接成员运算符(->)。或者是作用域解析符(::)。

     

    有时候。使用符号常量的作用域为类含实用。

    假设我写下例如以下代码,您可能觉得这样做是可行的

    class Bakery
    {
    private:
      const int Months=12;
      double costs[Months];
      ...
    }


    可是这是行不通的,由于声明类仅仅是描写叙述了对象的形态,并没有创建对象。

    因此在创建对象前。将没有存储值的空间。

    然而,有两种方式能够实现这个目标,而且效果同样。第一种是在类声明中声明一个枚举。在类声明中声明的枚举作用域为整个类,因此能够用枚举为整形常量提供作用域为整个类的符号名称。则上述代码能够这样写

    class Bakery
    {
    private:
      enum{Months=12};
      double costs[Months];
      ...
    }//这样的声明方式的枚举并不会创建类数据成员。也就是说全部对象都不会包括枚举。<strong>Month仅仅是一个符号名称。

    </strong>

    还有一种方式是使用keyword——static

    class Bakery
    {
    private:
      static const int Months=12;
      double costs[Months];
      ...
    }
    


    这个样将创建一个名为MOnth的常量,该常量将其与其它的静态变量存储在一起,而不是存储在对象中。

     

    9.3 抽象数据类型

    Stock类很详细。然而,程序猿经常通过定义类来表示更通用的概念。比如,就实现计算机专家所说的抽象数据类型(ADT)。顾名思义。ADT以通用的方式描写叙述数据类型,而没有引入语言或是实现细节。这里简要的给出栈的接口

    ifndef STACK_H_
    #define STATC_H_
    typedef unsigned liong Item;
    
    class Stack
    {
    private:
        enum{Max=10};
        Item items[10];
        int top;
    public:
        Stack();
        bool isempty() const;
        bool isfull();
        bool push(const Item &item);
        bool pop(Item& item);
    };
    
    #endif // STACK_H_


    接下来将会进入到类的使用部分

     

     

    9.4 运算符重载

    运算符重载是一种形式的C++多态。

    在这之前我们介绍过函数的重载或称为函数的多态。旨在让您可以使用同名的函数来完毕同样的基本操作。

    运算符重载将重载的概念扩展到运算符上,匀速赋予C++运算符多种含义。要重载运算符,需使用被称为运算符函数的特殊函数形式。其格式例如以下:

    <span style="font-size:18px;">operatorop(argument-list)</span>


    比如,operator+()重载+运算符,operate*()重载*运算符。

    op必须是一个有效的C++运算符,不能虚构一个新的运算符。不能重载@这个符号。

    以下我们来看一个运算符重载的演示样例:计算时间

    ifndef MYTH0_H_
    #definr MYTH0_H_
    
    class Time
    {
    private:
        int hours;
        int minutes;
    public:
        Time();
        Time(int h,int m=0);
        void AddMin(int m);
        void AddHr(int h);
        void Reset(int h=0,int m=0);
        Time Sum(const Time & t)const;
        void show() const;
    };
    #endif // MYTH0_H_


    这里给出mytime0.cpp

    include<iostream>
    #include"mytime0.h"
    
    Time::Time()
    {
        hours=minutes=0;
    }
    
    Time::Time(int h,int m)
    {
        hours=h;
        minutes=m;
    }
    
    void Time::AddMin(int m)
    {
        minutes+=m;
        hours+=minutes/60;
        minutes%=60;
    }
    
    void Time::AddHr(int h)
    {
        hours+=h;
    }
    
    void Time::Reset(int h,int m)
    {
        hours=h;
        minutes=m;
    }
    
    Time Time::Sum(const Time& t)const
    {
        Time sum;
        sum.minutes+t.minutes;
        sum.hours=hours+t.hours+sum.minutes/60;
        sum.minutes%=60;
        return sum;
    }
    
    void Time::Show() const
    {
        std::cout<<hours<<"hours,"<<minutes<<"minutes";
    }


    这个类比較基础,我就简单的说一下当中的一个函数Sum()。

    注意參数是引用,但返回的却不是引用。将參数声明为引用的目的是为了提高效率。假设按值传递Time对象,功能同样,可是效率明显不如引用。

    可是返回值不能是引用。因为sum是一个局部变量,当函数调用结束时,这个变量将不再存在。因此引用将指向一个不存在的变量。使用返回类型Time意味着程序将在删除sum之前构造它的拷贝。调用该函数将得到它的拷贝。

     

    9.5 加入重载运算符

    以下我们来给上面的函数加入重载函数。用operate+()来替换上述的sum()函数

    Time Time::operator+(const Time& t)const
    {
        Time sum;
        sum.minutes=sum.minutes+t.minutes;
        sum.hours=hours+t.hours+sum.minutes/60;
        sum.minutes%=60;
        return sum;
    }


    这样我们就能够这样调用operator+()方法

    total=coding.operator+(fixing);
    
    total=coding+fixing;//二者等价

    这两种方法都将调用operator方法。

    注意,在运算符表示法中,运算符左側的对象时调用对象。运算符右側的对象是作为參数被传递的对象。

    因此这种代码也是能够的

    Time t1,t2,t3,t4;
    t4=t1+t2+t3;//valid</span>


     

    9.6 重载的限制

    多数C++运算符都能够这种方式重载。

    重载的运算符不必是成员函数,但必须至少是有一个操作数是用户定义的类型。以下具体介绍其限制:

    (1)重载后的运算符必须至少有一个操作数使用户定义的类型,这将防止用户为标准类型重载运算符。比方。不能将-运算符用来计算两个数的和。

    (2)使用运算符时不能违反运算符原来的句法规则,比方,不饿能将%重载成一个操作数。也不能改动其优先级。

    (3)不能创建新的运算符,如@。

    (4)不能重载以下的运算符

    • sizeof:sizeof运算符;
    • . :成员运算符;
    • :::作用域解析运算符;
    • ?::条件运算符;
    • const_cast:强制类型转换运算符;
    • dynamic_cast:强制类型转换运算符;
    • static_cast:强制类型转换运算符;

    (5)多数运算符都能够通过成员或非成员函数进行重载,可是以下的运算符仅仅能通过成员函数进行重载。

    • =:赋值运算符;
    • ():函数调用运算符;
    • 【】下标运算符。
    • ->:通过指针訪问成员运算符

     

    好了,这次就到这里吧。

    好累啊,手都酸了。

  • 相关阅读:
    css 解决fixed 布局下不能滚动的问题
    js 正则常用函数 会正则得永生
    巧用call,appl有 根据对象某一属性求最大值
    锚点 , angular 锚点 vue锚点
    css 改变浏览器滚动条的样式
    angular 常用插件集合
    angular4,angular6 父组件异步获取数据传值子组件 undefined 问题
    angular组件之间的通讯
    tomcat的配置详解:[1]tomcat绑定域名
    click 绑定(三)防止事件冒泡
  • 原文地址:https://www.cnblogs.com/gavanwanggw/p/6917462.html
Copyright © 2011-2022 走看看