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]图 ...
随机推荐
- redids
Redis 地理位置(geo) Redis 键(key) Redis 字符串(String) Redis 哈希(Hash) Redis 列表(List) Redis 集合(Set) Redis 有序集 ...
- 从零开始学Docker
在写这篇博客之前,听说过Docker技术,但是一直没有主动去深入了解.用这篇博客来记录自己学习Docker的个人总结,会一直补充完善. 我这边先随便写,后期再做总结!! Docker官网: https ...
- [Android]简略的Android消息机制源码分析
相关源码 framework/base/core/java/andorid/os/Handler.java framework/base/core/java/andorid/os/Looper.jav ...
- [NWPU2016][寒假作业][正常版第三组]搜索和二分 N
题意,一条数轴上,告诉你起点和终点,只能向前走1,向后走1,或者走到二倍的现在的位置,每次都耗时一分钟.问从起点到终点的最短时长. 简单地bfs #include <iostream> # ...
- NET Core:部署项目到Ubuntu Server
NET Core:部署项目到Ubuntu Server 概述 基于上一篇成功安装Ubuntu Server 16.10的基础上,接下来继续我们ASP.NET Core项目的部署之旅! 只是对于这些年整 ...
- NET Core写了一个轻量级的Interception框架[开源]
NET Core写了一个轻量级的Interception框架[开源] ASP.NET Core具有一个以ServiceCollection和ServiceProvider为核心的依赖注入框架,虽然这只 ...
- D. Mike and distribution 首先学习了一个玄学的东西
http://codeforces.com/contest/798/problem/D D. Mike and distribution time limit per test 2 seconds m ...
- clickhouse源码Redhat系列机单机版安装踩坑笔记
前情概要 由于工作需要用到clickhouse, 这里暂不介绍概念,应用场景,谷歌,百度一大把. 将安装过程踩下的坑记录下来备用 ClickHouse源码 git clone安装(直接下载源码包安装失 ...
- Elasticsearch优化
2.out of memory错误 因为默认情况下es对字段数据缓存(Field Data Cache)大小是无限制的,查询时会把字段值放到内存,特别是facet查询,对内存要求非常高,它会把结果都放 ...
- 第十七章 提升用户体验 之 使用MVC扩展功能控制程序行为
1. 概述 ASP.NET MVC具有很好的扩展性,每一个核心功能都可以被扩展.重写 和 定制. 本章内容包括:实现MVC过滤器和controller工厂.使用 action results,view ...