IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> c++对类的的详解(2) -> 正文阅读

[C++知识库]c++对类的的详解(2)

知识点13【explicit关键字】

c++提供了关键字explicit,禁止通过构造函数进行隐式转换。声明为explicit的构造函数不能在隐式转换中使用。

#include <iostream>

using namespace std;


class Data
{
private:
    int num;
public:
    Data()
    {
        cout<<"Data无参构造"<<endl;
    }

        //初始化列表:对象名+() 显示调用 调用对象成员的构造函数
    explicit Data(int a):num(a)
    {
        //data =c;
        cout<<"Data有参构造"<<endl;
    }
    ~Data()
    {
        cout<<"Data析构函数"<<endl;
    }

};

int main(int argc, char *argv[])
{
    //当explicit修饰构造函数,不允许隐式转换
    Data data = 10;
    Data data1(15);//ok
    Data data2 = Data(20);//ok
    cout << "Hello World!" << endl;
    return 0;
}

运行结果:
在这里插入图片描述

知识点14【new和delete】从堆区申请空间

1、和malloc 、calloc、realloc比较

(1)malloc返回一个void指针,c++不允许将void赋值给其他任何指针,必须强转。
(2)malloc可能申请内存失败,所以必须判断返回值来确保内存分配成功。
(3)maloc不会调用构造函数,free不会调用析构函数(重要的)

2、new给基本类型申请空间

void test01(){
    int* a = new int;
    *a = 100;
    cout<<"*a = "<<*a<<endl;//100
    delete a;
}

new申请基本类型空间

void test02(){
    int *a = new int[5];//申请内容的时候,内容没有初始化,值随机。
    int *b = new int[5]{1,2,3,4,5};//值初始化。
    for(int i = 0; i < 5; i++){
        cout << a[i] << " ";
    }
    cout << endl;
    delete [] a;//new时加了[],delete也必须加[].
    for(int i = 0; i < 5; i++){
        cout << b[i] << " ";
    }
    cout << endl;
    delete [] b;

    //char *b = new char[15]{"hehe"};//错误
    char *arr = new char[15];
    strcpy(arr,"hehe");
    cout << arr << endl;
    delete [] arr;

}

运行结果:
在这里插入图片描述
注意:(1)new没有加[],delete释放的时候就不加[].
(2)new加[],delete释放的时候就加[].

3、new和delete给类对象申请空间

void test03(){
    //new按照Data申请空间,如果申请成功,会自动调用构造函数。
    Data *data = new Data();
    
    //先调用析构函数,在释放空间
    delete data;

}

运行结果:
在这里插入图片描述

class Data
{
private:
    int num;
    char *str;
public:
    Data()
    {
        cout<<"Data无参构造"<<endl;
    }

    //初始化列表:对象名+() 显示调用 调用对象成员的构造函数
    Data(int a,char *str1):num(a),str(str1)
    {
        cout<<"Data有参构造"<<endl;
    }
    ~Data()
    {
        cout<<"Data析构函数"<<endl;
    }
    void showData(){
        cout << num << " " << str << endl;
    }
};

void test04(){
    Data *data = new Data(100,"hehe");
    
    //因为data是指针,所以使用->,如果是普通对象,则使用.
    data->showData();

    delete data;
}

运行结果:
在这里插入图片描述

知识点15【对象数组】

本质还是数组,只是数组的每个元素是类的对象

void test05(){
    char *data = "hehehehe";//该方法只适合于字符串。char *data = {'w','s'}的方法是错误的,其他类型这样创建数组也是错误的。
    int arr[3];
    //对象数组arr1是数组,每个元素是Data类型的对象。
    //定义对象数组的时候,系统会自动给的数组中的每个元素调用构造函数。
    //自动调用无参构造
    Data arr1[5];
}

运行结果:
在这里插入图片描述

2、如果让对象数组中的元素调用有参构造,必须人为使用有参构造初始化

void test06(){
	//对象数组arr1是数组,每个元素是Data类型的对象
	//定义对象数组的时候 系统会自动给数组中的每个元素调用构造函数
	//人为为元素调用有参构造
	//初始化部分 调用有参构造 未初始化部分自动调用默认构造(无参构造)
    Data arr2[5] = {Data(50,"haha"),Data(60,"xixi")};
    //arr2[0]第0个元素,就是Data的对象
    arr2[0].showData();
    arr2[1].showData();
}

运行结果:
在这里插入图片描述

3、用new和delete申请对象数组

void test07(){
    Data *arr1 = new Data[5];//调用无参构造
    delete [] arr1;

    //第二种方法,调用有参构造
    Data *arr2 = new Data[5]{Data(50,"haha"),Data(60,"xixi")};
    
    //访问数组的不同方式
    (*arr2).showData();
    arr2[0].showData();
    (arr2+1)->showData();
    delete [] arr1;
}

运行结果:
在这里插入图片描述

4、尽量不要用delete释放void*

在这里插入图片描述
注意:没有析构 ,这是因为data1指向的类型未void,无法从void中寻找响应析构函数
在这里插入图片描述

5、malloc、free、和new 、delete不能混搭使用

知识点15【静态成员】static修饰的成员

成员:成员变量、成员函数
static修饰成员变量和成员函数
static声明为静态的,称为静态成员。不管这个类创建了多少对象,静态成员只有一个拷贝,这个拷贝被所有属于这个类的对象共享。
静态成员属于类,而不是对象。
在这里插入图片描述

1、static修饰成员变量

静态变量,是在编译阶段就分配空间,对象还没有创建时,就已经分配空间
静态变量必须在类内声明,类外定义(普通成员变量可以类内定义)。
静态数据成员不属于某个对象,在为对象分配空间中不包括静态成员所占的空间。

class Data2{
public:
    int num;//普通成员变量
    static int data;//静态成员变量

};
//定义的时候不需要加static
int Data2::data = 100;


void test(){

    //data是静态成员变量,是属于类的,可以通过类名称::直接访问
    cout << Data2::data << endl;//100

    //赋值
    Data2::data = 200;
    cout << Data2::data << endl;//200

   Data2 *ob1 = new Data2();
   //静态成员变量也可以使用对象名进行访问
   ob1->data = 300;
   cout << Data2::data << endl;//300

   Data2 *ob2 = new Data2();
   cout << ob2->data << endl;//300

   //普通成员变量只可以用成员名进行访问
   ob1->num = 100;
   cout << ob2->num << endl;//随机值
}

2、static修饰静态成员函数

class Data2{
private:
    int num;//普通成员变量
    static int data;//静态成员变量
public:
    //静态成员函数属于类而不属于对象
    static int getData(){
        return data;
    }

};
//定义的时候不需要加static
int Data2::data = 100;

void test10(){
    //静态成员函数可以通过类名直接访问
    cout << Data2::getData()<<endl;
    //也可以通过对象名进行访问
    Data2 *ob1 = new Data2();
    cout << ob-> getData() << endl;;
    
}

注意:1、静态成员函数的目的是操作静态成员数据
2、静态成员函数不能访问非静态成员数据。(静态成员函数内部没有this指针)
在这里插入图片描述
3、普通成员函数可以操作静态成员数据和非静态成员数据

class Data2{
private:
    int num;//普通成员变量
    static int data;//静态成员变量
public:
    int getNum(){
        num = 100;//no-static
        return data;//static
    }
    static int getData(){

        return data;
    }

};

4、静态成员变量和静态成员函数都有权限之分

3、const修饰静态成员

如果一个类的成员,既要实现共享,又要实现不可改变,那就用static const修饰

知识点16【静态成员案例】

案例一:静态成员统计类实例化对象的个数

#include <iostream>

using namespace std;


class Data
{
public:
    static int count;
public:
    Data()
    {
        cout<<"Data无参构造"<<endl;
        count++;
    }

    Data(const &ob){
        cout<<"Data拷贝构造"<<endl;
        count++;
    }

    ~Data()
    {
        cout<<"Data析构函数"<<endl;
        count--;
    }

};
int Data::count = 0;

int main(int argc, char *argv[])
{
    Data ob1;
    Data ob2;
    {
        Data ob3;
        Data ob4;
        cout << "对象个数:" << Data::count << endl;
    }
    cout << "对象个数:" << Data::count << endl;
    return 0;
}

运行结果:
在这里插入图片描述
案例2:单例模式–打印机(重要
步骤1:在单例类内部定义了一个Singletion类型的静态对象,作为外部共享的唯一实例。
步骤i2:提供一个公共静态的方法,让客户可以访问他的唯一实例。
步骤3:为了防止外部实例化其他对象,将其默认构造函数和拷贝构造函数设为私有。

class Printer{
private:
    //1、定义一个静态的对象指针变量,保存唯一实例地址
    static Printer *SignlePrint;
    //3、防止该类实例化其他对象,将构造函数全部私有化。
    Printer(){
        count = 0;
    }
    Printer(const Printer &ob){}
public:
    //2、提供一个静态方法,获得单例指针
    static Printer* getSignLePrint(){
        return SignlePrint;
    }
    //4、设置功能函数(自定义)
    void printText(char* str){
        cout << "打印" << str << endl;
        count++;
    }
    int count;
};

 Printer *Printer::SignlePrint = new Printer();

int main(int argc, char *argv[])
{
    //Printer printer;
    Printer *p1 = Printer::getSignLePrint();
    p1->printText("入职报告1");
    p1->printText("体检报告1");
    p1->printText("离职报告1");
    Printer *p2 = Printer::getSignLePrint();
    p2->printText("入职报告2");
    p2->printText("体检报告2");
    p2->printText("离职报告2");
    cout << p2->count << endl;
    return 0;
}

知识点17【this指针的引入】(重要)

c++的封装性:将数据和方法封装在一起,但数据和方法是分开存储的,每个对象拥有独立的数据,但方法是公用一份的。

1、this指针的引入

class Data2{
public:
    int m_num;
    void setNum(int num){
        m_num = num;
    }
};

int main(int argc, char *argv[])
{
    Data2 ob1 = Data2();
    ob1.setNum(10);
    cout << "ob1.m_num = " << ob1.m_num << endl;
    Data2 ob2 = Data2();
    ob2.setNum(20);
    cout << "ob2.m_num = " << ob2.m_num << endl;
    Data2 ob3 = Data2();
    ob3.setNum(30);
    cout << "ob3.m_num = " << ob3.m_num << endl;
    return 0;
}

运行结果:
在这里插入图片描述
分析:
在这里插入图片描述
上面的代码可以修改为:

class Data2{
public:
    int m_num;
    void setNum(int num){
        this->m_num = num;
    }
};

int main(int argc, char *argv[])
{
    Data2 ob1 = Data2();
    ob1.setNum(10);
    cout << "ob1.m_num = " << ob1.m_num << endl;
    Data2 ob2 = Data2();
    ob2.setNum(20);
    cout << "ob2.m_num = " << ob2.m_num << endl;
    Data2 ob3 = Data2();
    ob3.setNum(30);
    cout << "ob3.m_num = " << ob3.m_num << endl;
    return 0;
}

注意:

  1. this指针是隐含在对象成员函数内的一种指针
  2. 成员函数通过this指针即可知道操作的是哪个对象的数据
  3. 静态成员函数内部没有this指针,因此静态成员函数不能操作非静态成员变量(静态成员函数是属于类,函数内部没有this指针)

c++编译器对普通成员函数的内部处理:
在这里插入图片描述

知识点18【this指针的使用】

1、当形参名和成员变量名同名时,可用this指针来区分

class Data2{
public:
    int num;
    void setNum(int num){
        this->num = num;
    }
};

2、在类的普通成员函数中返回对象本身(*this)(重要)

class MyCout{
public:
    MyCout& myCout(char *str){
        cout << str;
        return *this;
    }
};


int main(int argc, char *argv[])
{
    MyCout ob = MyCout();
    ob.myCout("hehehe").myCout("hahaha").myCout("xixixi");//ob.myCout("hehe") == ob;
}

运行结果:
在这里插入图片描述

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-08-19 18:45:50  更:2022-08-19 18:49:01 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/12 20:43:59-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码