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

简介: 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;


相关文章
|
11月前
|
编译器 C++ 开发者
【C++篇】深度解析类与对象(下)
在上一篇博客中,我们学习了C++的基础类与对象概念,包括类的定义、对象的使用和构造函数的作用。在这一篇,我们将深入探讨C++类的一些重要特性,如构造函数的高级用法、类型转换、static成员、友元、内部类、匿名对象,以及对象拷贝优化等。这些内容可以帮助你更好地理解和应用面向对象编程的核心理念,提升代码的健壮性、灵活性和可维护性。
|
编译器 C++
C++之类与对象(完结撒花篇)(上)
C++之类与对象(完结撒花篇)(上)
|
11月前
|
编译器 C语言 C++
类和对象的简述(c++篇)
类和对象的简述(c++篇)
|
10月前
|
编译器 C++
类和对象(中 )C++
本文详细讲解了C++中的默认成员函数,包括构造函数、析构函数、拷贝构造函数、赋值运算符重载和取地址运算符重载等内容。重点分析了各函数的特点、使用场景及相互关系,如构造函数的主要任务是初始化对象,而非创建空间;析构函数用于清理资源;拷贝构造与赋值运算符的区别在于前者用于创建新对象,后者用于已存在的对象赋值。同时,文章还探讨了运算符重载的规则及其应用场景,并通过实例加深理解。最后强调,若类中存在资源管理,需显式定义拷贝构造和赋值运算符以避免浅拷贝问题。
|
10月前
|
存储 编译器 C++
类和对象(上)(C++)
本篇内容主要讲解了C++中类的相关知识,包括类的定义、实例化及this指针的作用。详细说明了类的定义格式、成员函数默认为inline、访问限定符(public、protected、private)的使用规则,以及class与struct的区别。同时分析了类实例化的概念,对象大小的计算规则和内存对齐原则。最后介绍了this指针的工作机制,解释了成员函数如何通过隐含的this指针区分不同对象的数据。这些知识点帮助我们更好地理解C++中类的封装性和对象的实现原理。
|
C++ 芯片
【C++面向对象——类与对象】Computer类(头歌实践教学平台习题)【合集】
声明一个简单的Computer类,含有数据成员芯片(cpu)、内存(ram)、光驱(cdrom)等等,以及两个公有成员函数run、stop。只能在类的内部访问。这是一种数据隐藏的机制,用于保护类的数据不被外部随意修改。根据提示,在右侧编辑器补充代码,平台会对你编写的代码进行测试。成员可以在派生类(继承该类的子类)中访问。成员,在类的外部不能直接访问。可以在类的外部直接访问。为了完成本关任务,你需要掌握。
278 19
|
10月前
|
编译器 C++
类和对象(下)C++
本内容主要讲解C++中的初始化列表、类型转换、静态成员、友元、内部类、匿名对象及对象拷贝时的编译器优化。初始化列表用于成员变量定义初始化,尤其对引用、const及无默认构造函数的类类型变量至关重要。类型转换中,`explicit`可禁用隐式转换。静态成员属类而非对象,受访问限定符约束。内部类是独立类,可增强封装性。匿名对象生命周期短,常用于临时场景。编译器会优化对象拷贝以提高效率。最后,鼓励大家通过重复练习提升技能!
|
存储 编译器 数据安全/隐私保护
【C++面向对象——类与对象】CPU类(头歌实践教学平台习题)【合集】
声明一个CPU类,包含等级(rank)、频率(frequency)、电压(voltage)等属性,以及两个公有成员函数run、stop。根据提示,在右侧编辑器补充代码,平台会对你编写的代码进行测试。​ 相关知识 类的声明和使用。 类的声明和对象的声明。 构造函数和析构函数的执行。 一、类的声明和使用 1.类的声明基础 在C++中,类是创建对象的蓝图。类的声明定义了类的成员,包括数据成员(变量)和成员函数(方法)。一个简单的类声明示例如下: classMyClass{ public: int
474 13
|
11月前
|
安全 编译器 C语言
【C++篇】深度解析类与对象(中)
在上一篇博客中,我们学习了C++类与对象的基础内容。这一次,我们将深入探讨C++类的关键特性,包括构造函数、析构函数、拷贝构造函数、赋值运算符重载、以及取地址运算符的重载。这些内容是理解面向对象编程的关键,也帮助我们更好地掌握C++内存管理的细节和编码的高级技巧。
|
11月前
|
存储 程序员 C语言
【C++篇】深度解析类与对象(上)
在C++中,类和对象是面向对象编程的基础组成部分。通过类,程序员可以对现实世界的实体进行模拟和抽象。类的基本概念包括成员变量、成员函数、访问控制等。本篇博客将介绍C++类与对象的基础知识,为后续学习打下良好的基础。