c++进阶这一篇就够啦!!!

4.4.2.3 const修饰成员函数
  1. 用const修饰的成员函数时,const修饰this指针指向的内存区域,成员函数体内不可以修改本类中的任何普通成员变量,
  1. 当成员变量类型符前用mutable修饰时例外。

//const修饰成员函数

class Person{

public:

Person(){

this->mAge = 0;

this->mID = 0;

}

//在函数括号后面加上const,修饰成员变量不可修改,除了mutable变量

void sonmeOperate() const{

//this->mAge = 200; //mAge不可修改

this->mID = 10; //const Person* const tihs;

}

void ShowPerson(){

cout << "ID:" << mID << " mAge:" << mAge << endl;

}

private:

int mAge;

mutable int mID;

};

int main(){

Person person;

person.sonmeOperate();

person.ShowPerson();

system("pause");

return EXIT_SUCCESS;

}

4.4.2.4 const修饰对象(常对象)
    1. 常对象只能调用const的成员函数
    2. 常对象可访问 const 或非 const 数据成员,不能修改,除非成员用mutable修饰

class Person{

public:

Person(){

this->mAge = 0;

this->mID = 0;

}

void ChangePerson() const{

mAge = 100;

mID = 100;

}

void ShowPerson(){

cout << "ID:" << this->mID << " Age:" << this->mAge << endl;

}

public:

int mAge;

mutable int mID;

};

void test(){

const Person person;

//1. 可访问数据成员

cout << "Age:" << person.mAge << endl;

//person.mAge = 300; //不可修改

person.mID = 1001; //但是可以修改mutable修饰的成员变量

//2. 只能访问const修饰的函数

//person.ShowPerson();

person.ChangePerson();

}

4.5 友元

类的主要特点之一是数据隐藏,即类的私有成员无法在类的外部(作用域之外)访问。但是,有时候需要在类的外部访问类的私有成员,怎么办?

解决方法是使用友元函数,友元函数是一种特权函数,c++允许这个特权函数访问私有成员。这一点从现实生活中也可以很好的理解:

比如你的家,有客厅,有你的卧室,那么你的客厅是Public的,所有来的客人都可以进去,但是你的卧室是私有的,也就是说只有你能进去,但是呢,你也可以允许你的闺蜜好基友进去。

程序员可以把一个全局函数、某个类中的成员函数、甚至整个类声明为友元。

4.5.1 友元语法

  1. friend关键字只出现在声明处
  2. 其他类、类成员函数、全局函数都可声明为友元
  3. 友元函数不是类的成员,不带this指针
  4. 友元函数可访问对象任意成员属性,包括私有属性

class Building;

//友元类

class MyFriend{

public:

//友元成员函数

void LookAtBedRoom(Building& building);

void PlayInBedRoom(Building& building);

};

class Building{

//全局函数做友元函数

friend void CleanBedRoom(Building& building);

#if 0

//成员函数做友元函数

friend void MyFriend::LookAtBedRoom(Building& building);

friend void MyFriend::PlayInBedRoom(Building& building);

#else

//友元类

friend class MyFriend;

#endif

public:

Building();

public:

string mSittingRoom;

private:

string mBedroom;

};

void MyFriend::LookAtBedRoom(Building& building){

cout << "我的朋友参观" << building.mBedroom << endl;

}

void MyFriend::PlayInBedRoom(Building& building){

cout << "我的朋友玩耍在" << building.mBedroom << endl;

}

//友元全局函数

void CleanBedRoom(Building& building){

cout << "友元全局函数访问" << building.mBedroom << endl;

}

Building::Building(){

this->mSittingRoom = "客厅";

this->mBedroom = "卧室";

}

int main(){

Building building;

MyFriend myfriend;

CleanBedRoom(building);

myfriend.LookAtBedRoom(building);

myfriend.PlayInBedRoom(building);

system("pause");

return EXIT_SUCCESS;

}

    [友元类注意]

  1. 友元关系不能被继承。
  2. 友元关系是单向的,类A是类B的朋友,但类B不一定是类A的朋友。
  3. 友元关系不具有传递性。类B是类A的朋友,类C是类B的朋友,但类C不一定是类A的朋友。

思考: c++是纯面向对象的吗?

如果一个类被声明为friend,意味着它不是这个类的成员函数,却可以修改这个类的私有成员,而且必须列在类的定义中,因此他是一个特权函数。c++不是完全的面向对象语言,而只是一个混合产品。增加friend关键字只是用来解决一些实际问题,这也说明这种语言是不纯的。毕竟c++设计的目的是为了实用性,而不是追求理想的抽象。

                                                       --- Thinking in C++

4.5.2 课堂练习

请编写电视机类,电视机有开机和关机状态,有音量,有频道,提供音量操作的方法,频道操作的方法。由于电视机只能逐一调整频道,不能指定频道,增加遥控类,遥控类除了拥有电视机已有的功能,再增加根据输入调台功能。

提示:遥控器类可作为电视机类的友元类。

class Remote;

class Television{

friend class Remote;

public:

enum{ On,Off }; //电视状态

enum{ minVol,maxVol = 100 }; //音量从0到100

enum{ minChannel = 1,maxChannel = 255 }; //频道从1到255

Television(){

mState = Off;

mVolume = minVol;

mChannel = minChannel;

}

//打开电视机

void OnOrOff(){

this->mState = (this->mState == On ? Off : On);

}

//调高音量

void VolumeUp(){

if (this->mVolume >= maxVol){

return;

}

this->mVolume++;

}

//调低音量

void VolumeDown(){

if (this->mVolume <= minVol){

return;

}

this->mVolume--;

}

//更换电视频道

void ChannelUp(){

if (this->mChannel >= maxChannel){

return;

}

this->mChannel++;

}

void ChannelDown(){

if (this->mChannel <= minChannel){

return;

}

this->mChannel--;

}

//展示当前电视状态信息

void ShowTeleState(){

cout << "开机状态:" << (mState == On ? "已开机" : "已关机") << endl;

if (mState == On){

cout << "当前音量:" << mVolume << endl;

cout << "当前频道:" << mChannel << endl;

}

cout << "-------------" << endl;

}

private:

int mState; //电视状态,开机,还是关机

int mVolume; //电视机音量

int mChannel; //电视频道

};

//电视机调台只能一个一个的调,遥控可以指定频道

//电视遥控器

class Remote{

public:

Remote(Television* television){

pTelevision = television;

}

public:

void OnOrOff(){

pTelevision->OnOrOff();

}

//调高音量

void VolumeUp(){

pTelevision->VolumeUp();

}

//调低音量

void VolumeDown(){

pTelevision->VolumeDown();

}

//更换电视频道

void ChannelUp(){

pTelevision->ChannelUp();

}

void ChannelDown(){

pTelevision->ChannelDown();

}

//设置频道 遥控新增功能

void SetChannel(int channel){

if (channel < Television::minChannel || channel > Television::maxChannel){

return;

}

pTelevision->mChannel = channel;

}

//显示电视当前信息

void ShowTeleState(){

pTelevision->ShowTeleState();

}

private:

Television* pTelevision;

};

//直接操作电视

void test01(){

Television television;

television.ShowTeleState();

television.OnOrOff(); //开机

television.VolumeUp(); //增加音量+1

television.VolumeUp(); //增加音量+1

television.VolumeUp(); //增加音量+1

television.VolumeUp(); //增加音量+1

television.ChannelUp(); //频道+1

television.ChannelUp(); //频道+1

television.ShowTeleState();

}

//通过遥控操作电视

void test02(){

//创建电视

Television television;

//创建遥控

Remote remote(&television);

remote.OnOrOff();

remote.ChannelUp();//频道+1

remote.ChannelUp();//频道+1

remote.ChannelUp();//频道+1

remote.VolumeUp();//音量+1

remote.VolumeUp();//音量+1

remote.VolumeUp();//音量+1

remote.VolumeUp();//音量+1

remote.ShowTeleState();

}

4.5 强化训练(数组类封装)

MyArray.h

#ifndef MYARRAY_H

#define MYARRAY_H

class MyArray{

public:

//无参构造函数,用户没有指定容量,则初始化为100

MyArray();

//有参构造函数,用户指定容量初始化

explicit MyArray(int capacity);

//用户操作接口

//根据位置添加元素

void SetData(int pos, int val);

//获得指定位置数据

int GetData(int pos);

//尾插法

void PushBack(int val);

//获得长度

int GetLength();

//析构函数,释放数组空间

~MyArray();

private:

int mCapacity; //数组一共可容纳多少个元素

int mSize; //当前有多少个元素

int* pAdress; //指向存储数据的空间

};

#endif

MyArray.cpp

#include"MyArray.h"

MyArray::MyArray(){

this->mCapacity = 100;

this->mSize = 0;

//在堆开辟空间

this->pAdress = new int[this->mCapacity];

}

//有参构造函数,用户指定容量初始化

MyArray::MyArray(int capacity){

this->mCapacity = capacity;

this->mSize = 0;

//在堆开辟空间

this->pAdress = new int[capacity];

}

//根据位置添加元素

void MyArray::SetData(int pos, int val){

if (pos < 0 || pos > mCapacity - 1){

return;

}

pAdress[pos] = val;

}

//获得指定位置数据

int MyArray::GetData(int pos){

return pAdress[pos];

}

//尾插法

void MyArray::PushBack(int val){

if (mSize >= mCapacity){

return;

}

this->pAdress[mSize] = val;

this->mSize++;

}

//获得长度

int MyArray::GetLength(){

return this->mSize;

}

//析构函数,释放数组空间

MyArray::~MyArray(){

if (this->pAdress != nullptr){

delete[] this->pAdress;

}

}

TestMyArray.cpp

#include"MyArray.h"

void test(){

//创建数组

MyArray myarray(50);

//数组中插入元素

for (int i = 0; i < 50; i++){

//尾插法

myarray.PushBack(i);

//myarray.SetData(i, i);

}

//打印数组中元素

for (int i = 0; i < myarray.GetLength(); i++){

cout << myarray.GetData(i) << " ";

}

cout << endl;

}

4.6 运算符重载

4.6.1 运算符重载基本概念

运算符重载,就是对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型。(运算符重载不能改变本来寓意,不能改变基础类型寓意)

    运算符重载(operator overloading)只是一种语法上的方便,也就是它只是另一种函数调用的方式。

在c++中,可以定义一个处理类的新运算符。这种定义很像一个普通的函数定义,只是函数的名字由关键字operator及其紧跟的运算符组成。差别仅此而已。它像任何其他函数一样也是一个函数,当编译器遇到适当的模式时,就会调用这个函数。

语法:

   定义重载的运算符就像定义函数,只是该函数的名字是operator@,这里的@代表了被重载的运算符。函数的参数中参数个数取决于两个因素。

  1. 运算符是一元(一个参数)的还是二元(两个参数);
  2. 运算符被定义为全局函数(对于一元是一个参数,对于二元是两个参数)还是成员函数(对于一元没有参数,对于二元是一个参数-此时该类的对象用作左耳参数)

代码:示例代码\49 []运算符重载

   [两个极端]

   有些人很容易滥用运算符重载。它确实是一个有趣的工具。但是应该注意,它仅仅是一种语法上的方便而已,是另外一种函数调用的方式。从这个角度来看,只有在能使涉及类的代码更易写,尤其是更易读时(请记住,读代码的机会比我们写代码多多了)才有理由重载运算符。如果不是这样,就改用其他更易用,更易读的方式。

   对于运算符重载,另外一个常见的反应是恐慌:突然之间,C运算符的含义变得不同寻常了,一切都变了,所有C代码的功能都要改变!并非如此,对于内置的数据类型的表示总的所有运算符是不可能改变的。我们不能重载如下的运算符改变其行为。

1 + 4;

4.6.2 运算符重载碰上友元函数

友元函数是一个全局函数,和我们上例写的全局函数类似,只是友元函数可以访问某个类私有数据。

案例: 重载左移操作符(<<),使得cout可以输出对象。

class Person{

friend ostream& operator<<(ostream& os, Person& person);

public:

Person(int id,int age){

mID = id;

mAge = age;

}

private:

int mID;

int mAge;

};

ostream& operator<<(ostream& os, Person& person){

os << "ID:" << person.mID << " Age:" << person.mAge;

return os;

}

int main(){

Person person(1001, 30);

//cout << person; //cout.operator+(person)

cout << person << " | " << endl;

return EXIT_SUCCESS;

}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Jenkins进阶篇主要涉及到在Jenkins中使用多分支管道来进行持续集成、持续传送和持续部署的操作。首先,你需要准备好Git库,并按照指南在不同平台上安装Jenkins。接下来,你可以使用多分支管道来配置Jenkins以实现集成、测试和交付等阶段。这些阶段可以根据正在构建的分支进行选择性地执行。例如,你可以添加“交付和生产部署”阶段,并且在该阶段中添加当分支为"development"时的执行步骤和当分支为"production"时的执行步骤。在这些步骤中,你可以指定要执行的脚本命令,例如运行测试、部署到开发环境或部署到生产环境。你也可以在适当的阶段添加交互式输入,以便在执行过程中进行人工干预。最后,你可以使用Jenkinsfile来定义整个多分支管道的流程和步骤。这样,你就可以在Jenkins中实现更高级的持续集成和部署方案。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [Jenkins | 进阶篇 | 端对端多分支Pipeline](https://blog.csdn.net/weixin_37417954/article/details/83412133)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [Jenkins进阶篇](https://download.csdn.net/download/weixin_26704349/19545011)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值