第二章 微观部分:面向对象之类的组成

  • 函数
    • 构造函数
    • 析构函数
    • 拷贝构造函数
    • 运算符重载函数
    • ==封装一个字符串类==
  • 初始化列表
  • 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++基础】第二章 微观部分:面向对象之类的组成相关推荐

  1. 计算机技术的应用 课件,计算机技术及应用基础――第二章ppt课件

    <计算机技术及应用基础――第二章ppt课件>由会员分享,可在线阅读,更多相关<计算机技术及应用基础――第二章ppt课件(64页珍藏版)>请在人人文库网上搜索. 1.第二章 VB ...

  2. 计算机文化基础第二章,计算机文化基础(第二章Windows2000操作系统)

    计算机文化基础(第二章Windows2000操作系统) 第二章Windows 2000 操作系统1. 打开"资源管理器"的方法不能是_A右击"开始"按钮 B选择 ...

  3. 计算机网络基础 第二章

    第二章 数据通信基础 2.1 基本知识 2.1.1 信息,数据和信号 数据分为模拟数据和数字数据. 模拟数据:在某个区间内连续变化的值,例如声音和电压是幅度连续变化的波形 数字数据:在某个区间内离散的 ...

  4. Python基础——第二章:Python基础语法

    前言 本文是根据黑马程序员Python教程所作之笔记,目的是为了方便我本人以及广大同学们查漏补缺. 不想做笔记直接来我的频道.当然啦,自己的笔记才是最好的哦! PS:感谢黑马程序员! 教程链接:黑马程 ...

  5. 第二章《计算机系统》复习测试,职中计算机应用基础第二章测试题及答案

    傅连仲主编教材,第二章 Windows XP操作系统 的单元复习题. 13级<计算机应用基础>第二章测试题 满分100分,考试时间 90分钟 A.不确定 B.被强制关闭 C.被暂时挂起 D ...

  6. 第二章计算机应用基础试题答案,职中计算机应用基础第二章测试题及答案(3页)-原创力文档...

    - PAGE PAGE 2 欢迎下载 13级<计算机应用基础>第二章测试题 满分100分,考试时间 90分钟 姓名: 成绩: 一.单选题(共40分,每题2分) 1.删除当前输入的错误字符, ...

  7. 计算机操作系统只有windows对不对,计算机应用基础 第二章 操作系统

    第二章 操作系统 一.判断题(正确的填A,错误的填B) *1.在Windows桌面的任务栏中,显示的是所有已打开的窗口图标. A **2.Windows不允许用户进行系统(Config)配置. B * ...

  8. html第二章课后选择题答案,心理学基础第二章 课后习题

    第二章 一.单项选择题: ( )1.神经系统最基本的结构和功能单位是 . A. 树突 B.轴突 C.神经元 D.细胞体 ( )2.大脑左半球的 受损会导致听觉性失语症,即病人不能理解口语单词. A. ...

  9. JAVA基础第二章 面向对象进阶

    2.1封装与getter.setter方法 1.读写是两个操作,读即取值.访问值,写即赋值. 2.面向对象的三大特征:封装.继承.多态 (1)封装--一个程序肯定会定义很多类,那么为了保证各个类之间数 ...

最新文章

  1. SpringBoot-hello world
  2. 2021年跨境电商市场怎么样?新手商家入驻还有机会吗?
  3. 雷林鹏分享:jQuery EasyUI 数据网格 - 条件设置行背景颜色
  4. virt-manager 使用 shh 远程访问配置方法
  5. 关于json格式字符串解析并用mybatis存入数据库
  6. 再学 GDI+[16]: GDI+ 的颜色常量表
  7. [Usaco2015 dec]Breed Counting
  8. struts内的action方法自动提交
  9. 快速找出Linux服务器上不该存在恶意或后门文件
  10. 2021 ICPC Asia Jinan Regional Contest-J Determinant(取模高斯消元)
  11. hive表指定分区字段搜索_hive导出分区表到mysql 分区字段值怎么取
  12. Unable to modify the parent container element before the child element is closed
  13. UI原型设计软件Axure
  14. DZ60通过IIC读取LM75温度遇到问题解决方法
  15. Windows 7驱动自动安装设置及手动更新方法
  16. 大内高手—常见内存错误
  17. C++ 求幂函数pow()的输出问题
  18. 关于笔试遇到的题 1
  19. 数据增广:旋转,缩放,平移以及错切
  20. 求n+nn+nnn+nnnn+nnnnn+nnnnnn

热门文章

  1. 小程序源码:炫酷手持滚动弹幕生成小工具微信小程序-多玩法安装简单
  2. 420集的python教程视频_GitHub - kaisar420/codeparkshare: Python初学者(零基础学习Python、Python入门)书籍、视频、资料、社区推荐...
  3. H3C 交换机配置命令详解
  4. Mann-Whitney U检验
  5. 干货 | 5G全面基础知识
  6. 前端针对不同技术的常用UI框架和图表
  7. C语言下实现冰雹猜想的算法
  8. WebSocket爬虫
  9. C语言之随机数函数( rand() )的使用方法
  10. Robot Framework之打开浏览器