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]图 ...
随机推荐
- layui实现下拉分类多级
Layui tree 下拉菜单树 1.效果: 2.html 代码: <!DOCTYPE html> <html> <head> <meta charse ...
- 安卓下点击a标签不跳转;点击a标签在手机真机上会调出手机键盘的解决办法
安卓下点击a标签不跳转的解决办法,是不用href做跳转的链接,改为用JS控制跳转 <a href="javascript:;" ontouchstart="wind ...
- SpringBoot用户CRUD
1.准备 http://start.spring.io/ 这里地址去直接生成你需要的项目信息,如何你本身ide以及集成了springboot 那么可以直接生成项目信息 需要的知识:java,sprin ...
- Web自动化测试—PO设计模式(三)
test_case目录下面放你要执行的用例 目录结构 ui_auto_test --src --test_case --__init.py --test_login_case --pages --__ ...
- Java中List,Set和Map详解及其区别和使用场景(转)
https://www.cnblogs.com/EasonJim/p/7967138.html
- Ubuntu同时忘记用户密码和root密码
在设置密码的时候,用到了小键盘,重启后再次用小键盘输入密码时,发现输入的并不是数字,而是其他符号.所以在设置关键信息的时候,小键盘还是得慎用啊. 解决方案: 在引导界面也就是开机倒计时的时候,按下 e ...
- c++笔记2
一 继承和多态.虚函数:类不必重复造轮子,可以从其它基类派生而来(多重继承(由多个基类的特点)和虚拟继承(基类的一些特性在继承之间共享)).派生类需要在自己的头文件中包含基类头文件,切派生类声明要指明 ...
- tyvj P4877 _1.组合数
时间限制:1s 内存限制:256MB [问题描述] 从m个不同元素中,任取n(n≤m)个元素并成一组,叫做从m个不同元素中取出n个元素的一个组合:从m个不同元素中取出n(n≤m)个元素的所有组合的个数 ...
- Country roads take me home, to the place I belong.
Country roads take me home, to the place I belong.故乡的路,带我回家吧,回到我期盼已久的归宿.
- hadoop完全分布式模式搭建和hive安装
简介 Hadoop是用来处理大数据集合的分布式存储计算基础架构.可以使用一种简单的编程模式,通过多台计算机构成的集群,分布式处理大数据集.hadoop作为底层,其生态环境很丰富. hadoop基础包括 ...