C++ 学习笔记(五)类的知识小结一(重载,友元函数,静态成员,new)
---恢复内容开始---
学习C++类知识点还是挺多的,每个知识点学习的时候都觉得这个知识点咋那么多东西,其实真学完了再回头看好像也就那么点。这次用程序写一个黑猫揍白猫的故事总结一下这段时间学习的零碎知识点。包括以下几点:
1.重载:函数重载 、运算符重载
2.友元函数
3.静态成员变量
4.new / delete 关键字和 malloc / free函数的区别
程序将实现一个Cat类,定义一只黑猫一只白猫。用户喂食黑猫为黑猫增加武力值,之后用户给白猫喂食,为白猫增加生命值,两只猫都喂食完后黑猫就揍白猫一次。等到白猫生命值为0时或者食物喂完了程序结束(原谅我想不到更好的、又简单、又能符合想记录的知识点需求 的故事,只能无厘头的让白猫一直挨揍了)。。。
Cat类的定义:Cat.h
#pragma once
#include <iostream>
#include <string> #define CAT_ATTRIBUTE 1 #define FORCE_MAX 100
#define HP_MAX 100 #define CAT_MALE 1+CAT_ATTRIBUTE
#define CAT_FEMALE 2+CAT_ATTRIBUTE using namespace std; class Cat
{
/*公有成员:此类的对象可以直接使用*/
public:
static int food; //静态成员变量 Cat(string name ,int sex = CAT_MALE); //构造函数,创建一个对象时自动调用
Cat(string name ,int sex , unsigned int force_value = ); //函数的重载
~Cat(); //析构函数,没有返回值没有传参,delete对象时自动调用 int add_hp(int add_value); //普通成员函数
void report_state(); //普通成员函数
int get_hp();
int eat_food(int value);
friend unsigned int add_force(Cat *cat,int add_value); //友元函数(全局函数可访问类的私有成员) int operator-(Cat *cat); //- 运算符重载
int operator--(); //前置-- 运算符重载
int operator--(int); //后置-- 运算符重载(使用占位参数说明是后置运算符重载) /*私有成员:只能通过本类的公有函数和友元函数进行读写*/
private:
string name;
int sex; //性别
int HP; //生命值
unsigned int force_value; //武力值 };
Cat类的实现:Cat.cpp
#include "cat.h" int Cat::food = ; //初始化静态变量
Cat::Cat(string name ,int sex) //构造函数,创建一个对象时自动调用
{
/*设置初始值*/
this->name = name;
this->sex = sex;
this->HP = ;
this->force_value = ;
/*打印状态*/
cout<<" creat a new cat !! "<<endl;
this->report_state();
} Cat::Cat(string name ,int sex , unsigned int force_value ) //构造函数,创建一个对象时自动调用
{
/*设置初始值*/
this->name = name; this->sex = sex;
this->HP = ;
this->force_value = force_value;
/*打印状态*/
cout<<" creat a new cat !! "<<endl;
this->report_state(); } Cat::~Cat()//析构函数,没有返回值没有传参,delete对象时自动调用
{
cout<<"cat "<<this->name<<" was dead"<<endl;
} void Cat::report_state()
{
cout<< " ---------I am "<<this->name<<"----------" <<endl;
cout<< "my hp :"<<this->HP<<endl;
cout<< "my force value:"<<this->force_value<<endl;
cout<<"-------------------------------------"<<endl;
} int Cat::add_hp(int add_value)
{
this->HP += add_value;
return this->HP;
} int Cat::operator-(Cat *cat)//- 运算符重载
{
cat->HP -= this->force_value;
if(cat->HP < )
cat->HP = ;
cout<<this->name<<" hit - > "<<cat->name<<endl;
return cat->HP;
} int Cat::operator--()//前置-- 运算符重载
{
if(this->HP > )
this->HP -=;
return this->HP;
} int Cat::operator--(int)//后置-- 运算符重载(使用占位参数说明是后置运算符重载)
{
int temp = this->HP;
if(this->HP > )
this->HP -=; return temp;
} int Cat::get_hp()
{
return this->HP;
} int Cat::eat_food(int value)//将减少静态成员变量food的值
{
food -= value;
if(Cat::food<){
cout<<"food is used up !!"<<endl;
Cat::food = ;
}
return Cat::food;
} /*友元函数 可以通过传入对象 操作其私有属性*/
unsigned int add_force(Cat *cat,int add_value)
{
cat->force_value += add_value;
if(cat->force_value > FORCE_MAX)
cat->force_value = FORCE_MAX;
return cat->force_value;
}
main函数:main.cpp
#include <iostream>
#include <string>
#include "cat.h" using namespace std;
int main(int argc, char **argv)
{
int add_value = ;
Cat black("black",CAT_MALE,); //黑猫出生(调用构造函数)
Cat* white;
white = new Cat("white"); //白猫出生( 函数重载;new将分配堆中的内存,使用完毕需要delete) black--; //黑猫作死,扣一点血(后置--运算符重载)
cout<<"black cat's HP :"<<black.get_hp()<<endl; --*white; //白猫学黑猫作死,扣一点血(前置--运算符重载)
cout<<"white cat's HP:"<<white->get_hp()<<endl; /*如果黑猫白猫都还活着并且还有食物程序继续运行*/
while(black.get_hp() > && white->get_hp()> &&Cat::food )
{
cout<<"How much food do you want to feed for black cat "<<endl;
cin>>add_value;
black.eat_food(add_value);
cout<<"black's force :"<<add_force(&black,add_value)<<"\n"<<endl; //调用友元函数添加黑猫武力值 cout<<"How much food do you want to feed for white cat "<<endl;
cin>>add_value;
white->eat_food(add_value); //将减少静态成员food的值,这个food是整个Cat类共享的
cout<<"white's hp :"<<white->add_hp(add_value)<<"\n"<<endl; black-white; //‘-’运算符重载的使用
cout<<"white cat's HP"<<white->get_hp()<<endl;
cout<<"food still have "<<Cat::food<<endl;
} white->report_state();
black.report_state();
delete white; //使用new分配的内存需要释放
system("pause");
return ;
}
运行结果:

知识点总结:
1.函数重载 、参数默认值
本次例程中实现了两个Cat构造函数,传入参数不同
a.定义
Cat(string name ,int sex = CAT_MALE); //构造函数,创建一个对象时自动调用
Cat(string name ,int sex , unsigned int force_value = 20); //函数的重载
函数重载的判断标准是传参:传参的个数,传参的类型。
返回值不能作为函数重载的标准,即传参一样返回值类型不同的是会被认为函数重定义的。
b.使用
在main函数9行,定义black 的时候传入了三个参数很明显是调用了
Cat(string name ,int sex , unsigned int force_value = 20);
在new一个white的时候只传入了一个参数,其实调用了
Cat(string name ,int sex = CAT_MALE);
在Cat.h文件中我们可以看到sex = CAT_MALE;当没有传参的时候便使用这个默认参数。
而从黑猫的创建中因为传入force_value = 10,所以默认的20失效。

2.运算符重载
本例程重载了-、后置--、前置-- 三个运算符。运算符重载其实也是实现函数,只是函数名比较固定。友元函数可以访问私有成员,所以友元函数也能实现运算符重载,本例程使用成员函数进行运算符重载。
运算符重载的语法:
返回值类型 类名 :: operator op (参数)(operator是运算符重载关键字,op是要重载的运算符。)
后置---与前置--的区分方式在于后置--有int占位参数(利用C++函数重载的特性)
int Cat::operator-(Cat *cat)//- 运算符重载 int Cat::operator--() //前置-- 运算符重载 int Cat::operator--(int) //后置-- 运算符重载(使用占位参数说明是后置运算符重载)
一元重载:
个人理解是操作的对象只有一个,前置--和后置--属于一元重载,在重载函数实现中使用this指针既可以操作相应的成员
后置-- 和 前置-- 函数名是一样的。不同的是后置运算符重载有一个占位传参,这是编译器分辨这是前置还是后置运算符重载的标志。
二元重载:
操作对象有两个,‘-’ 运算符重载属于二元重载。
例如:
50 int Cat::operator-(Cat *cat)//- 运算符重载
51 {
52 cat->HP -= this->force_value;
53 if(cat->HP < 0)
54 cat->HP = 0;
55 cout<<this->name<<" hit - > "<<cat->name<<endl;
56 return cat->HP;
57 }
a-b;
此时在函数实现中,this指针操作的变量属于a,b则作为重载函数的传参。
2.友元函数
友元函数就是可以操作对象私有属性的函数。只要在类的定义中声明即可。

使用 friend 关键字,这个函数不是这个类的成员函数而是一个全局函数,可以通过传入参数cat来操作其私有成员,如果不是友元函数就算传入对象也不能操作其私有成员。

3.静态成员变量
静态成员变量是一个类所有对象共享的参数(个人理解成一个类的全局变量),本例程中Cat::food 就是静态成员变量,黑猫和白猫调用eat_food函数是两个不同对象操作了food成员,food减少了两次。

静态成员的定义:
1.先在定义类的时候声明

2.在C文件中给一个初始值

访问静态成员可以使用以下两种方法:
例:
Cat a("a");
a.food = 100;
Cat::food = 100;
4.new / delete 关键字和 malloc / free函数的区别
在本次例程中使用了两种创建对象的方法

使用new产生的是一个指针,之后操作white都是使用指针操作。

white是指针,使用前置-- 要先解引用(*white),如果没有解引用指针white就指到天南地北去了。
new创建的对象将分配堆的内存,与malloc一样。new也可以用于创建数组,变量等数据结构,malloc能做的事情new都能做。
malloc和new的那些事:
1.都是分配堆内存,使用完毕后需要释放
2.如果分配基础数据结构(暂时实验了除了类之外),malloc/free 、new/delete是可以互换的。即new出来的变量可以使用free释放,malloc的变量可以使用delete释放
3.分配类时,new将会调用构造函数,delete调用析构函数,所以创建类的时候不能使用malloc和free。
---恢复内容结束---
C++ 学习笔记(五)类的知识小结一(重载,友元函数,静态成员,new)的更多相关文章
- python学习笔记(五):装饰器、生成器、内置函数、json
一.装饰器 装饰器,这个器就是函数的意思,连起来,就是装饰函数,装饰器本身也是一个函数,它的作用是用来给其他函数添加新功能,比如说,我以前写了很多代码,系统已经上线了,但是性能比较不好,现在想把程序里 ...
- (转)Qt Model/View 学习笔记 (五)——View 类
Qt Model/View 学习笔记 (五) View 类 概念 在model/view架构中,view从model中获得数据项然后显示给用户.数据显示的方式不必与model提供的表示方式相同,可以与 ...
- Typescript 学习笔记五:类
中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...
- C#可扩展编程之MEF学习笔记(五):MEF高级进阶
好久没有写博客了,今天抽空继续写MEF系列的文章.有园友提出这种系列的文章要做个目录,看起来方便,所以就抽空做了一个,放到每篇文章的最后. 前面四篇讲了MEF的基础知识,学完了前四篇,MEF中比较常用 ...
- java之jvm学习笔记五(实践写自己的类装载器)
java之jvm学习笔记五(实践写自己的类装载器) 课程源码:http://download.csdn.net/detail/yfqnihao/4866501 前面第三和第四节我们一直在强调一句话,类 ...
- Learning ROS for Robotics Programming Second Edition学习笔记(五) indigo computer vision
中文译著已经出版,详情请参考:http://blog.csdn.net/ZhangRelay/article/category/6506865 Learning ROS for Robotics Pr ...
- ES6学习笔记<五> Module的操作——import、export、as
import export 这两个家伙对应的就是es6自己的 module功能. 我们之前写的Javascript一直都没有模块化的体系,无法将一个庞大的js工程拆分成一个个功能相对独立但相互依赖的小 ...
- muduo网络库学习笔记(五) 链接器Connector与监听器Acceptor
目录 muduo网络库学习笔记(五) 链接器Connector与监听器Acceptor Connector 系统函数connect 处理非阻塞connect的步骤: Connetor时序图 Accep ...
- python3.4学习笔记(五) IDLE显示行号问题,插件安装和其他开发工具介绍
python3.4学习笔记(五) IDLE显示行号问题,插件安装和其他开发工具介绍 IDLE默认不能显示行号,使用ALT+G 跳到对应行号,在右下角有显示光标所在行.列.pycharm免费社区版.Su ...
- 【opencv学习笔记五】一个简单程序:图像读取与显示
今天我们来学习一个最简单的程序,即从文件读取图像并且创建窗口显示该图像. 目录 [imread]图像读取 [namedWindow]创建window窗口 [imshow]图像显示 [imwrite]图 ...
随机推荐
- cmd 中粘贴复制(转)
1 如右图,右键命令提示符窗口的标题栏,选择属性. 2 选择“编辑选项”里的“快速编辑模式”,并确定之: 3 在弹出的应用选择提示框上选择“保存属性,供以后具有相同标题的窗口使用”: 4 如此你就可以 ...
- Maven入门 项目的生命周期&pom.xml配置&仓库
- 077 Combinations 组合
给定两个整数 n 和 k,返回 1 ... n 中所有可能的 k 个数的组合.例如,如果 n = 4 和 k = 2,组合如下:[ [2,4], [3,4], [2,3], [1,2], [ ...
- STM32之CAN
概述:STM32有3个发送邮箱,发送调度器根据优先级决定先发送那个,相当于有3个发送帧FIFO;接收方面有14个过滤器,通过编程可以从CAN的接收引脚中选择需要的报文然后分别给2个接收帧FIFO(每个 ...
- Ubuntu18.10设置静态IP、DNS、卸载无用软件
设置静态IP root@xueji:~# vim /etc/network/interfaces # interfaces() ) and ifdown() auto lo iface lo inet ...
- (转)C#抽象类和接口对比
c#中抽象类(abstract)和接口(interface)的相同点与区别 转自:http://blog.csdn.net/fxh_hua/archive/2009/08/20/4464739.as ...
- B. Game of the Rows
B. Game of the Rows time limit per test 1 second memory limit per test 256 megabytes input standard ...
- 原创 html动态表格
<table id="opttb"> <asp:Repeater ID="tempOptions" runat="server&qu ...
- 《移动Web前端高效开发实战》笔记1——静态布局在移动端上的自适应
1.整体缩放 整体缩放可以用在营销活动页,营销活动可能因为设计美观需求必须使用背景图片而非背景色,因此需要考虑背景图适应屏幕大小.开发者可以用320像素的宽度作为基础宽度(高度可以固定),然后通过计算 ...
- 【js类库AngularJs】解决angular+springmvc的post提交问题
[js类库AngularJs]解决angular+springmvc的post提交问题 AngularJS诞生于2009年,由Misko Hevery 等人创建,后为Google所收购.是一款优秀的前 ...