【c++基础】第二章 微观部分:面向对象之类的组成
第二章 微观部分:面向对象之类的组成
- 类
- 函数
- 构造函数
- 析构函数
- 拷贝构造函数
- 运算符重载函数
- ==封装一个字符串类==
- 初始化列表
- this指针
- 常对象和常成员函数(方法)
- 静态属性和静态成员函数
- ==单例设计模式==
类
对象:属性和方法组成,是类的一个实例化
类(class):具有相同属性和方法,是对象的抽象
类的封装性:权限(public/private/protected)+属性+方法
类的大小(和结构体相似):
空类,1byte;类对象的大小与类中的非静态属性相关,类对象共享类中的成员函数的地址
练习:
#include <iostream>using namespace std;class rectangle{int wide;int length;
public:void setwide(int wide){this->wide=wide;}void setlength(int length){this->length=length;}int getArea(){return this->wide*this->length;}
};rectangle& compair(rectangle& r1,rectangle& r2){return r1.getArea()>r2.getArea()?r1:r2;
}int main()
{int wide=10;int length=20;rectangle *rect1=new rectangle();rect1->setwide(wide);rect1->setlength(length);cout << "rectangle's area1 = " << rect1->getArea() << endl;wide=20;length=30;rectangle rect2;rect2.setwide(wide);rect2.setlength(length);cout << "rectangle's area2 = " << rect2.getArea() << endl;cout << "---------------------------------------------------" << endl;cout << "较大的面积为:" << endl;cout << compair(*rect1,rect2).getArea() << endl;return 0;
}
函数
类中函数(类的骨架):
- 构造函数
- 析构函数
- 可被构造函数
- 运算符重载函数
- 取值运算符
- 长取值运算符
构造函数
没有任何返回值,函数名与类名相同,由编译器根据对象定义参数决定
- 不存在,编译器生成一个无参的空构造
- 存在,编译器不在生成
- 意义:对类对象属性进行初始化,
类中get()/set()函数的升级
#include <iostream>using namespace std;class stu{string name;int age;
public:stu(){cout << "stu的无参构造" << endl;}stu(string name,int age){ this->name=name;this->age=age;cout << "stu的有参构造" << endl;}void showInfo(){cout << "姓名:" << this->name << " 年龄:" << this->age << endl;}
};int main()
{stu s1;
// stu s1();//是一个函数声明,并非是无参函数的调用stu s2("yao",18);s2.showInfo();stu *s3=new stu("yaoliang",19);s3->showInfo();delete s3;return 0;
}
显示(explicit)调用和隐式(implicit expression) 调用
#include <iostream>using namespace std;class A{int a;
public:A(){cout << "i am is NULL structure" << endl;}A(int a){cout << "i am is single structure" << endl;}A(int a,int b){cout << "i am is more structure" << endl;}explicit A(int a,int b,int c){cout << "i am is more more structure" << endl;}
};int main()
{cout << " explicit structure " << endl ;A a;A a1(1);A a2(1,2);A a3(1,2,3);cout << " implicit expression strcture" << endl ;A a4 = 1;A a5 = {1,2};
// A a6 = {1,2,3};//在类构造函数前加上explicit,无法隐式调用return 0;
}
析构函数
#include <iostream>using namespace std;class stu{string name;int age;int *p;
public:stu(string name,int age){this->name=name;this->age=age;this->p=new int[1024];cout << "stu structure" << endl;}~stu(){delete []p;cout << "stu destruct" << endl;}
};int main()
{stu s1("zhangsan",10);stu *s2 = new stu("yao",18);delete s2;return 0;
}
好处:避免内存泄漏,先清理资源,在销毁空间
拷贝构造函数
类中没有提供拷贝构造函数,当出现使用其他对象为本对象进行初始化时,编译器自动生成,以供调用
浅拷贝:
- 优点:简单赋值,可以提高效率
- 缺点:指针共享一块内存,析构后,内存被回收
#include <iostream>using namespace std;class stu{string _name;int _age;int *_score;
public:stu(string name,int age,int *score){this->_name=name;this->_age=age;this->_score=new int[10] ();memcpy(this->_score,score,10);
// this->_score=score;cout << "stu structure" << endl;}~stu(){delete [] _score;cout << "stu destruct" << endl;}stu(const stu& other){this->_name=other._name;this->_age=other._age;
// this->_p=other._p;//深拷贝this->_score=new int[10];memmove(this->_score,other._score,sizeof(int[10]));cout << "stu copy" <<endl;}void showInfo()const{cout << "姓名: " << this->_name ;cout << "年龄: " << this->_age ;cout << "成绩: " << this->_score[0] ;cout << endl;}int getAge()const{return this->_age;}
};const stu& compair(const stu& s1,const stu& s2){return s1.getAge()>s2.getAge()?s2:s1;
}//多拷贝3次
//stu compair(stu s1,stu s2){
// return s1.getAge()>s2.getAge()?s2:s1;
//} int main()
{int score[10]={100,80,40};//显示调用stu s1("yaoliang",18,score);stu s2(s1);s2.showInfo();//隐式调用stu s3("minmin",17,score);stu s4=s3;s4.showInfo();cout << "-----------stu's age compair ,input small age imformation------------" << endl;compair(s2,s4).showInfo();return 0;
}
引用可以提高深拷贝的运行效率,使用常引用,保证实参安全
运算符重载函数
面向对象服务,全局也可以定义,但类中优先,存在深浅拷贝(针对=)
等号运算符重载函数,深拷贝要谨慎
stu& operator=(const stu& other){this->_name=other._name;this->_age=other._age;//判空,删除原空间,创建新空间if(this->_score!=nullptr){delete []_score;} this->_score=new int[10] ();memcpy(this->_score,other._score,10);cout << "stu equal operator overloading" <<endl;return *this;
}
测试代码:
#include <iostream>using namespace std;class stu{string _name;int _age;int *_score;
public:stu(string name,int age,int *score){this->_name=name;this->_age=age;this->_score=new int[10] ();memcpy(this->_score,score,10);
// this->_score=score;cout << "stu structure" << endl;}~stu(){delete [] _score;cout << "stu destruct" << endl;}stu(const stu& other){this->_name=other._name;this->_age=other._age;
// this->_p=other._p;//深拷贝this->_score=new int[10];memmove(this->_score,other._score,sizeof(int[10]));cout << "stu copy" <<endl;}//系统默认stu& operator=(const stu& other){this->_name=other._name;this->_age=other._age;//要必须小心if(this->_score!=nullptr){delete []_score;} this->_score=new int[10] ();memcpy(this->_score,other._score,10);cout << "stu equal operator overloading" <<endl;return *this;}//自定义加法int operator+(const stu& other){return this->getAge()+other.getAge();}//自定义减法int operator-(const stu& other){cout << "class inside" << endl;return this->getAge()+other.getAge();}void showInfo()const{cout << "姓名: " << this->_name ;cout << "年龄: " << this->_age ;cout << "成绩: " << this->_score[0] ;cout << endl;}int getAge()const{return this->_age;}
};const int operator-(const stu& s1,const stu& s2){cout << "class external" << endl;return s1.getAge()-s2.getAge();
}const stu& compair(const stu& s1,const stu& s2){return s1.getAge()>s2.getAge()?s2:s1;
}//stu compair(stu s1,stu s2){
// return s1.getAge()>s2.getAge()?s2:s1;
//}int main()
{int score[10]={100,80,40};//显示调用stu s1("yaoliang",18,score);stu s2(s1);s2.showInfo();//隐式调用stu s3("minmin",17,score);stu s4=s3;s4.showInfo();s3=s2;s3.operator=(s2);s3.showInfo();//系统自动创建了一个等号运算符重载cout << "---stu's age compair ,input small age imformation----" << endl;compair(s2,s4).showInfo();cout << "--using operator overloading (overall situation) ,stu age sub--" << endl;cout << s1-s4 << endl;cout << operator-(s1,s4) << endl;cout << "-----------using operator overloading ,stu age add------------" << endl;cout << s1+s4 << endl;return 0;
}
注意:
- 在全局不可重载的运算符:=,->,[],()
- 不能重载:.(.运算符),::(域运算符),.*(. *运算符),?:(三目运算符),(sizeof运算符),(#预处理运算符)
自增自减运算符
前自增
返回值 operator++()
后自增:
返回值 operator++(int)//亚元
#include <iostream>
#include <unistd.h>using namespace std;class Clock{int min;int sec;
public:Clock(int m,int s){this->min=m;this->sec=s;}Clock& operator++(){++sec;if(0==sec%60){++min;sec=0;if(0==min%60){this->min=0;}}return *this;}Clock& operator++(int){sec++;if(sec%60==0){min++;sec=0;if(min%60==0){this->min=0;}}return *this;}//Clock& operator++(int){// this->operator++();// (*this).operator++();// return ++*this;//三种效果一致//}void display(){cout << this->min << ":" << this->sec << endl;}
};int main()
{Clock c(0,0);while(true){c++;c.display();sleep(1);}return 0;
}
封装一个字符串类
#include <iostream>
#include <string.h>
using namespace std;class MyString{
private:char* m_data;
public://MyString无参空构造MyString(){this->m_data=new char[1];this->m_data[0]='\0';}//MyString有参构造:在c++中字符串常量的类型,一定是const char* 类型MyString(const char* c_str){int len=strlen(c_str);this->m_data=new char[len+1];memmove(this->m_data,c_str,len);this->m_data[len]='\0';}//MyString 的拷贝构造MyString(const MyString& other){int len=strlen(other.m_data);this->m_data=new char[len+1];memmove(this->m_data,other.m_data,len);this->m_data[len]='\0';}//=号运算符重载函数MyString& operator=(const MyString& other){if(this==&other){return *this;}int len=strlen(other.m_data);if(nullptr!=this->m_data){delete [] m_data;this->m_data=new char[len+1];}else{this->m_data=new char[len+1];}memmove(this->m_data,other.m_data,len);this->m_data[len]='\0';return *this;}//析构~MyString(){delete []m_data;this->m_data=nullptr;}//查找下标元素char operator[](int index){if(index < 0 || index >= strlen(this->m_data)){cout << "cross the border" << endl;}return this->m_data[index];}//加法运算MyString operator+(const MyString& other){int my_len=strlen(this->m_data);int other_len=strlen(other.m_data);char *temp=new char[my_len+other_len+1];memmove(temp,this->m_data,my_len);memmove(temp+my_len,other.m_data,other_len);temp[my_len+other_len]='\0';MyString temp_str=temp;delete [] temp;return temp_str;}char* getM_data()const{return this->m_data;}
};
ostream& operator << (ostream& cout,const MyString& other){cout << other.getM_data();return cout;
}int main()
{MyString str;MyString str1("hello");MyString str2=str1;MyString str3="yao";MyString str4="liang";cout << str1.getM_data() << endl;cout << str1 << endl;cout << str2 << endl;cout << str1[2] << endl;cout << str3+str4 << endl;return 0;
}
初始化列表
const修饰的常属性(只读属性)的初始化方式。
在C++中const修饰的对象,必要初始化
类中构造函数的特殊语法(高效率):
类中构造函数的初始化列表,早于构造函数,在对象开辟空间时,解决const问题
初始化列表语法:在类中构造函数后+:类中的属性(外部参数)
遵循原则:顺序初始化(忽略static修饰的属性)
#include <iostream>using namespace std;class Score{int score;
public:Score(int score){cout << this->score << endl;}
};class stu{string _name;int _age=128;int _salary;string *_friend;Score _s=Score(100);
public:stu(string name,int age):_name(name),_age(age),_salary(10000),_friend(new string[10]{"sunsun"}),_s(Score(100)){cout << "stu的有参构造" << endl;}~stu(){delete []_friend;cout << "stu destruct" << endl;}void showInfo(){cout << "姓名:" << this->_name << " 年龄:" << this->_age ;cout << "工资:" << this->_salary << " 朋友1:" << this->_friend[0] ;cout << endl;}
};int main()
{stu s1("yaoliang",18);s1.showInfo();Score s(10);return 0;
}
this指针
在c中的体现:
#include <stdio.h>typedef void (*Pfunc_t)();typedef struct Stu
{char *name;int age;Pfunc_t f;
}stu;void showInfo(stu *const this){printf("姓名:%s,年龄:%d\n",this->name,this->age);
}int main(int argc, const char *argv[])
{/*your code*/stu s={"yaoliang",20,showInfo};s.f(&s);return 0;
}
C++中this指针
- 就是本对象的起始地址(const修饰的常地址)
- 是隐藏(非静态)在成员函数最左侧的一个常变量形参
两种用法:
- 区分属性名与形参名
- 解引用,返回本对象
#include <iostream>using namespace std;class Stu{string name;int age;
public://1.当成员函数中形参变量与类属性变量重名时,使用this加以区分Stu(string name,int age){this->name=name;this->age=age;
// name=name;//error
// age=age;//error}void showInfo(){cout << "姓名: " << this->name << " , 年龄: " << this->age << endl;
// cout << "姓名: " << name << " , 年龄: " << age << endl;//error}//2.返回本对象 *thisStu& setName(string name){this->name=name;return *this;}
};int main()
{Stu stu("yaoliang",18);stu.showInfo();stu.setName("liang").showInfo();return 0;
}
常对象和常成员函数(方法)
常对象,const修饰的对象
特性:
只读,不可修改
不能调用普通成员函数(有修改权限),只能调用常函数
常函数,const修饰的函数
特性:
- 不修改函数类中的属性,只读
#include <iostream>using namespace std;class rectangle{int wide;int length;
public:
// rectangle(int wide,int length){
// this->wide=wide;
// this->length=length;
// }void setwide(int wide){this->wide=wide;}void setlength(int length){this->length=length;}int getArea()const{return this->wide*this->length;}
};//更安全
const rectangle& compair(const rectangle& r1,const rectangle& r2){return r1.getArea()>r2.getArea()?r1:r2;
}//rectangle& compair( rectangle& r1,rectangle& r2){
// r1.setwide(10);
// r1.setlength(100000);
// return r1.getArea()>r2.getArea()?r1:r2;
//}int main()
{int wide=10;int length=20;rectangle *rect1=new rectangle();rect1->setwide(wide);rect1->setlength(length);cout << "rectangle's area1 = " << rect1->getArea() << endl;wide=20;length=30;rectangle rect2;rect2.setwide(wide);rect2.setlength(length);cout << "rectangle's area2 = " << rect2.getArea() << endl;cout << "---------------------------------------------------" << endl;cout << "较大的面积为:" << endl;cout << compair(*rect1,rect2).getArea() << endl;return 0;
}
静态属性和静态成员函数
特点:
静态属性**资源共享**
静态属性隐藏于类域之中,可以通过域名+::(域名访问符)直接访问
静态成员函数访问不到类中属性,原因:最左侧没有常变量形参this
静态成员函数可以访问静态属性,与静态属性类似,不依赖于某个对象调用
static修饰
- 修饰属性时,修饰的是属性的存储形式,需要在类外全局
.cpp
文件中定义:例:stu::count=0;
- 修饰函数时,修饰的是级别,隐藏在本类的类域中,为全类服务,可以域名::方式直接调用
- 修饰属性时,修饰的是属性的存储形式,需要在类外全局
#include <iostream>using namespace std;class stu{string _name;const int _age=128;int _salary;string *_friend;static int count;
public:stu(string name,int age):_name(name),_age(age),_salary(10000),_friend(new string[10]{"sunsun"}){count++;cout << "stu的有参构造" << endl;}~stu(){delete []_friend;cout << "stu destruct" << endl;}void showInfo(){cout << "姓名:" << this->_name << " 年龄:" << this->_age ;cout << "工资:" << this->_salary << " 朋友1:" << this->_friend[0] ;cout << endl;}static int get_count(){return count;}
};//需要在全局定义的原因:
//静态变量在声明时就需要开辟空间,而在类中不会开辟空间
int stu::count = 0;int main()
{stu s1("yaoliang",18);s1.showInfo();cout << "count = " << stu::get_count() << endl;//1return 0;
}
单例设计模式
一个类,在外部只能生成一个实例,最大限度的减小资源占用
以下为**饿汉式**:
- 优点:线程安全
- 缺点:占用一块堆上的资源
#include <iostream>using namespace std;
class singleton{
private://1.把类中的构造设置为私有singleton(){cout << "singleton的构造" << endl;}static singleton* my_instance;
public://2.提供一个公有接口函数返回本对象的指针//3.公有接口不想依赖类对象的调用,是不是应该把该接口升级为static静态成员函数static singleton* getInstance(){//4.在类私有属性中定义一个静态的私有成员对象类型的属性指针,并把公有接口中返回出去return my_instance;}
};//5.在类外完成对类中静态属性指针的初始化
singleton* singleton::my_instance=new singleton();int main()
{singleton* s1=singleton::getInstance();singleton* s2=singleton::getInstance();singleton* s3=singleton::getInstance();cout << s1 << endl;cout << s2 << endl;cout << s3 << endl;return 0;
}
以下为**懒汉式**:
- 优点:不用不占用资源
- 缺点:
- 生成死递归,所以懒汉不提供析构,只能自己创建
- 不在使用全部申请的空间,线程不安全,所以要加智能锁
#include <iostream>
#include <mutex>
using namespace std;//设置全局锁
mutex mtx;class singleton{
private://1.把类中的构造设置为私有singleton(){cout << "singleton的构造" << endl;}static singleton* my_instance;
public://2.提供一个公有借口函数返回本对象的指针//3.公有接口不想依赖类对象的调用,是不是应该把该接口升级为static静态成员函数static singleton* getInstance(){//4.在类私有属性中定义一个静态的私有成员对象类型的属性指针,并把公有接口中返回出去//c++11智能锁类型(可被析构):lock_guard<mutex> lock(mtx);//c++11线程安全的懒汉式单例if(nullptr==my_instance){my_instance =new singleton();}return my_instance;}//懒汉式析构void destroy(){if(nullptr!=my_instance){delete my_instance;my_instance=nullptr;}}//析构
// ~singleton(){delete my_instance;//生成死递归,所以懒汉不提供析构
// }
};//5.在类外完成对类中静态属性指针的初始化
singleton* singleton::my_instance=nullptr;int main()
{singleton* s1=singleton::getInstance();singleton* s2=singleton::getInstance();singleton* s3=singleton::getInstance();cout << s1 << endl;cout << s2 << endl;cout << s3 << endl;return 0;
}
注意:类中的静态属性当其初始化时,可以调用类中的私有属性和方法
【c++基础】第二章 微观部分:面向对象之类的组成相关推荐
- 计算机技术的应用 课件,计算机技术及应用基础――第二章ppt课件
<计算机技术及应用基础――第二章ppt课件>由会员分享,可在线阅读,更多相关<计算机技术及应用基础――第二章ppt课件(64页珍藏版)>请在人人文库网上搜索. 1.第二章 VB ...
- 计算机文化基础第二章,计算机文化基础(第二章Windows2000操作系统)
计算机文化基础(第二章Windows2000操作系统) 第二章Windows 2000 操作系统1. 打开"资源管理器"的方法不能是_A右击"开始"按钮 B选择 ...
- 计算机网络基础 第二章
第二章 数据通信基础 2.1 基本知识 2.1.1 信息,数据和信号 数据分为模拟数据和数字数据. 模拟数据:在某个区间内连续变化的值,例如声音和电压是幅度连续变化的波形 数字数据:在某个区间内离散的 ...
- Python基础——第二章:Python基础语法
前言 本文是根据黑马程序员Python教程所作之笔记,目的是为了方便我本人以及广大同学们查漏补缺. 不想做笔记直接来我的频道.当然啦,自己的笔记才是最好的哦! PS:感谢黑马程序员! 教程链接:黑马程 ...
- 第二章《计算机系统》复习测试,职中计算机应用基础第二章测试题及答案
傅连仲主编教材,第二章 Windows XP操作系统 的单元复习题. 13级<计算机应用基础>第二章测试题 满分100分,考试时间 90分钟 A.不确定 B.被强制关闭 C.被暂时挂起 D ...
- 第二章计算机应用基础试题答案,职中计算机应用基础第二章测试题及答案(3页)-原创力文档...
- PAGE PAGE 2 欢迎下载 13级<计算机应用基础>第二章测试题 满分100分,考试时间 90分钟 姓名: 成绩: 一.单选题(共40分,每题2分) 1.删除当前输入的错误字符, ...
- 计算机操作系统只有windows对不对,计算机应用基础 第二章 操作系统
第二章 操作系统 一.判断题(正确的填A,错误的填B) *1.在Windows桌面的任务栏中,显示的是所有已打开的窗口图标. A **2.Windows不允许用户进行系统(Config)配置. B * ...
- html第二章课后选择题答案,心理学基础第二章 课后习题
第二章 一.单项选择题: ( )1.神经系统最基本的结构和功能单位是 . A. 树突 B.轴突 C.神经元 D.细胞体 ( )2.大脑左半球的 受损会导致听觉性失语症,即病人不能理解口语单词. A. ...
- JAVA基础第二章 面向对象进阶
2.1封装与getter.setter方法 1.读写是两个操作,读即取值.访问值,写即赋值. 2.面向对象的三大特征:封装.继承.多态 (1)封装--一个程序肯定会定义很多类,那么为了保证各个类之间数 ...
最新文章
- SpringBoot-hello world
- 2021年跨境电商市场怎么样?新手商家入驻还有机会吗?
- 雷林鹏分享:jQuery EasyUI 数据网格 - 条件设置行背景颜色
- virt-manager 使用 shh 远程访问配置方法
- 关于json格式字符串解析并用mybatis存入数据库
- 再学 GDI+[16]: GDI+ 的颜色常量表
- [Usaco2015 dec]Breed Counting
- struts内的action方法自动提交
- 快速找出Linux服务器上不该存在恶意或后门文件
- 2021 ICPC Asia Jinan Regional Contest-J Determinant(取模高斯消元)
- hive表指定分区字段搜索_hive导出分区表到mysql 分区字段值怎么取
- Unable to modify the parent container element before the child element is closed
- UI原型设计软件Axure
- DZ60通过IIC读取LM75温度遇到问题解决方法
- Windows 7驱动自动安装设置及手动更新方法
- 大内高手—常见内存错误
- C++ 求幂函数pow()的输出问题
- 关于笔试遇到的题 1
- 数据增广:旋转,缩放,平移以及错切
- 求n+nn+nnn+nnnn+nnnnn+nnnnnn
热门文章
- 小程序源码:炫酷手持滚动弹幕生成小工具微信小程序-多玩法安装简单
- 420集的python教程视频_GitHub - kaisar420/codeparkshare: Python初学者(零基础学习Python、Python入门)书籍、视频、资料、社区推荐...
- H3C 交换机配置命令详解
- Mann-Whitney U检验
- 干货 | 5G全面基础知识
- 前端针对不同技术的常用UI框架和图表
- C语言下实现冰雹猜想的算法
- WebSocket爬虫
- C语言之随机数函数( rand() )的使用方法
- Robot Framework之打开浏览器