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>

另一种方式是使用关键字——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)多数运算符都可以通过成员或非成员函数进行重载,但是下面的运算符只能通过成员函数进行重载。

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

 

好了,这次就到这里吧。好累啊,手都酸了。。。

C++ Primer Plus的若干收获--(九),布布扣,bubuko.com

C++ Primer Plus的若干收获--(九)

上一篇:Tomcat6.0 only supports J2EE 1.2, 1.3, 1.4, and Java EE 5 Web modules


下一篇:Html5 页面中 JavaScript 启动调用的三种方法比较