Essential C++第4章 基于对象的编程风格

第4章 基于对象的编程风格

这一章,我们会设计并属于实现我们自己的class。

在之前的几章,我们已经指定Class的一些相关事项。

1、使用Class之前,要包含相应的头文件

2、class名称被视为一个类型,就像int,double一样。

3、class会提供一组操作函数,让我们作用于其object上。

4、class由两部分组成:一组公开的操作函数;一组私有的实现细节。

 

 

 

4.1 如何实现一个Class

我们从实现一个 栈(stack)开始,实现一个class。

什么是栈呢,栈是一种存放数据的结构,它允许我们在里面存放数值,并以 后进先出的顺序取出。我们以pushing 方式存入数值,以popping方式取出数值。

用户可能还需要其他操作,如查询stack空间是否已满(full),是否为空(empty),查询stack元素个数(size)。

 

Class的声明以关键字 class开始,随后接一个class名称:

class stack;

 

class的定义类似这样:

class Stack {

public:

 //…public接口

private:

//…private实现部分

};

  class 定义有两部分:class声明,主体。

  主体中的public和private是访问权限,public 可被程序任何地方访问,private只能被class内部或class friend 访问。

  stack class的定义如下:

class Stack{

public:

bool push(const string&);

bool pop(string &elem);

bool peek(string &elem);

bool empty();

bool full();

int size() { return _stack.size();}

private:

vector<string> _stack;

};

所有的member function都要在Class内声明,如果在Class内定义,则会自动被视为inline函数。在Class外定义,必须用特殊的语法:

inline bool

Stack::empty()

{

return _stack.empty();

}

 

bool

Stack::pop(string &elem)

{

if(empty())

  return false;

elem = _stack.back();

_stack.pop_back();

return true;

}

 

Inline函数和Class定义 都放在对应的,h文件中。

非inline函数应该放在和class同名的.cpp文件中。

下面是Stack member function 的定义。

inline bool Stack::full()

{return _stack.size() == _stack.max_size();}

 

bool Stack::peek(string &elem)

{

if(empty())

  return false;

elem = _stack.back();

return true;

}

bool Stack::push(const string &elem)

{

if(full())

  return false;

_stack.push_back(elem);

return true;

}

 

 

 

4.2 构造函数和析构函数

编译器会在每次class object被定义时,调用构造函数(constructor)来进行初始化。

constructor(构造函数)的名称必须和Class名称相同。constructor没有返回值类型,可以被重载。

最简单的constructor是default constructor,它不需要接受参数。

参数表为空 或者为每个参数提供默认值。

 

Member initialization List(成员初始化列表)

Triangular::Triangular(const Triangular &rhs)

:_length(rhs._length),_beg_pos(rhs._beg_pos),_next(rhs._beg_pos-1)

{}

Member initialization list 紧接在参数列表的最后的冒号后面,是个以逗号分隔的列表。

 

 

destructor(析构函数)

析构函数是class名称加上~前缀,没有返回值,也没有参数。用来释放对象的资源(释放内存。析构函数由系统自动调用。

 

Memberwise initialization(成员逐一初始化)

即当使用一个对象给另一个对象初始化时,对象中的成员会逐一复制。

有时默认的复制操作不符合我们的要求,我们要自定义copy constructor。

类似于:

Matrix:Matrix(const Martrix &rhs){

}

 

 

 

4,3 mutable(可变)可const(不变)

class 设计者在Member function身上标注const,告诉编译器,这个Member function 不会更改Class Object中的内容。

const修饰符写于函数参数列表之后,凡是在Class主体以外定义者,如果他是一个const member function ,它必须在声明和定义处都指定const。

 

Member function 可以根据const与否而重载,因此可以设计这样的重载函数:

const BigClass& val() cosnt(return _val);

BigClass& val(){return _val};

 

针对const的mutable, 将某个成员标示为mutable,就可以宣称,对这个成员的修改不会破坏class object的常量性。(在const member function中可以修改这个成员)

 

4.4 this指针

this指针时Member function内用来指向其调用者的指针。

 

4.5 静态类成员

static(静态)data member用来表示唯一的,可以共享的Member。它可以在同一类的所有对象中被访问。

对Class而言,static data member只有唯一的一份实体。因此我们必须在代码文件中提供清楚的定义。

//.cpp

vector<int> Triangular::elems;

如果在class member function内部访问static data member,其访问方式和访问一般数据成员相同。

const static int data member可以在声明时指定初值。

 

Static Member function(静态成员函数)

static可以不用任何具体的对象调用:

如 Triangular::is_elem(7);

并且为了不和具体的对象有关,static Member function 不能访问non-static member。

static Member function的声明方式是在原函数前加关键字static。

在Class主体外进行定义时,无需再加static(此规则也适用于static data member)。

4.6 打造一个Iterator Class

我们可以像定义Member function那样定义运算符,运算符函数和普通函数很像,区别是它的名称就是operator加运算符号。

bool  operator==(const Triangular_iterator &) const;

int operatir*()const;

运算符重载的规则:

1、不能引入新的运算符

2、运算符操作数个数不可变

3、运算符优先级不变

4、运算符函数的参数列表至少有一个是class类型的。

 

运算符定义的方式可以向Member function一样,

也可以像non member function一样

Non member function 运算符的参数列表中,一定会比Member运算符多一个参数,也就是this指针。对于Member运算符来说,这个this指针隐式代表左操作数。

 

前++ 和后++

前++的参数表是空的,

后++的参数表得有一个int参数 inline Triangula_iterator Tirangular_iterator::

operator++(int)

{..

return …;

}

但使用时不需要传入这个int参数,编译器自动设置为0。

直接使用

it++;

即可。

 

 

4.7 friend 友类

class可以将其他function或class指定为friend,这样就可以让他们具备和class member function相同的访问权限,可以访问class 的private member。

只要在某个函数的原型前加上关键字friend就可以将它声明为某个class的关键字。

如果让class A 认为class B是自己的friend,则class B的所有函数都是A的friend。

 

 

 

4.8实现复制运算符(copy assignment operator)

只要为Class提供copy assignmemnt operator,它就会被用来取代默认的memberwise copy。

 

 

4.9 实现一个function object

function object 是一种提供有function call运算符的class。

通常我们将function object 作为参数传递给泛型算法。

function call运算符:

例:

inline bool LessThan::operator()(int value) const {return value<_val;}

 

 

4.10 重载iostream运算符

为了让我们的class支持

cout<<train<<endl;这种形式,我们需要重载iostream运算符。

ostream & operator<<(ostream &os, const Triangular &rhs)

{

 os<<”(“<<rhs._beg_pos()<<”,”<<rhs.length()<<”,”;

rhs.display(rhs.length(),rhs._beg_pos(),os);

return os;

}

类似的可以重载>>运算符。

 

 

4.11 指针,指向Class Member Function

指向成员函数的指针和指向普通函数的指针很像,都需要指定返回类型和参数列表。

不过指向成员函数的指针还要指定 所属的class

如:

void (num_sequence::*pm)(int) = 0;

 

取得某个member function 的地址,对函数名词使用&运算符。,函数名称前要加class scope运算符限定。

pm = &num_sequence::Fibonacci;

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一只大鸽子

如有帮助,欢迎关注同名公众号

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值