C++学习03

一.  c++中的类(核心)

1.类的三大特征:  封装 继承 多态

  1. 封装:
  • 将功能接口(函数)封装到类中使用
  • 把数据成员封装到类中使用
  1. 继承 :
  • 子类 继承 父类的接口或者数据

        优点: 

          子类直接继承父类的接口函数, 就不需要重新开发接口

      提高了代码的复用性 有利于软件版本的升级

  1. 多态
  • 一个对象作用于不同的事物,所得到的结果(功能)不同

优点: 提高了代码的复用性

2.类的定义

语法:

C++
class 类名{

    成员列表;

    方法....
}

以上类的定义是最简单的定义方式,没有什么意义,默认成员和方法都是私有的,外界无法访问

需要修饰符来修饰成员和方法:

public  公有的                -------  外界可以访问

protected  受保护的     -------  外界不可以访问

private  私有的              -------  外界不可以访问

二. C++中的构造函数

构造函数:

1 函数名和类名相同

2 函数没有返回值

3 函数不需要用户调用,创建对象的时候自动调用

构造函数作用: 用于定义对象时,初始化对象的数据成员

语法:

C++
class  类名{

    public:

    类名(){
        //构造函数
    }

}

案例:

C++
//定义类
class base{
    public:
    // 构造函数必须写在public公共区
    // 否则 无法创建对象
    //构造函数----函数名和类名同名
    //无参构造函数
    base(){
        cout << "创建对象,自动调用构造函数" << endl;
    }

    //带参构造函数
    base(int a){
        num = a;
        cout << num << endl;
    }

    private:
    int num;
};

int main(int argc, char const *argv[])
{
    //定义对象调用构造函数  -- 无参
    base a;
    //定义对象时传入参数   --  带参
    base b(10086);
    return 0;
}

注意:

  • 构造函数必须写在公共区public里, 因为定义对象时会自动调用, 只有在公共区才可以被外界直接访问调用
  • 假设用户没写任何的构造函数,系统会自动生成无参构造函数

练习: 设计一个学生类,公有成员姓名name(char *),保护成员money(double),私有成员密码pwd(int)

C++
定义一个构造函数初始化这些数据成员 并写一个输出接口
#include <iostream>
using namespace std;
extern "C"{
    #include <string.h>

}
/*
设计一个学生类,
公有成员姓名name(char *),
保护成员money(double),
私有成员密码pwd(int)
定义一个构造函数初始化这些数据成员
并写一个输出接口
*/
class Stu{
    public:
    char name[40];

    //解决方式1: 函数重载
    // Stu(){
    //     cout << "构造函数被调用" << endl;
    // }

    //正常步骤
    // Stu(const char * n,double m, int p){
    //     cout << "构造函数被调用" << endl;
    //     //初始化
    //     strncpy(name,n,strlen(n)+1);
    //     money = m;
    //     pwd = p;
    // }

    //解决方式2: 默认参数
    //构造函数
    Stu(const char * n="ZQ",double m=1.34, int p=123456){
        cout << "构造函数被调用" << endl;
        //初始化
        strncpy(name,n,strlen(n)+1);
        money = m;
        pwd = p;
    }
    void show(){
        cout << "name:" << name << endl;
        cout << "money:" << money << endl;
        cout << "pwd:" << pwd << endl;
    }

    protected:
    double money;


    private:
    int pwd;
};

int main(int argc, char const *argv[])
{
    //定义对象  -- 必须传参
    Stu obj("ZQ",12345567.8,123456);
    //调用接口
    obj.show();

    //想法: 创建对象时 不传递参数 -- 简化
    // 解决方式1: 函数重载
    // Stu pp;

    //解决方式2: 默认参数
    Stu pp;

    return 0;
}

总结:

构造函数支持函数重载

  • 构造函数可以设置默认参数

三. this关键字

this指针的作用:

  • 用来区分类内成员和类外成员
  • 每当用户创建一个类,这个类内部就会自动生成一个this指针, 指向当前类的首地址

C++
#include <iostream>
using namespace std;

// 给构造函数传参并输出
class base{
    public:
    //构造函数
    base(int a,int b,int c){
        cout << "&this:" << this << endl;
        //this指针 指向是内部成员
        // 用来和外部成员做区分
        this->a = a;  //this是指针 使用 ->
        this->b = b;
        this->c = c;
    }

    void show(){
        cout << a << endl;
        cout << b << endl;
        cout << c << endl;

    }

    private:
    int a;
    int b;
    int c;

};

int main(int argc, char const *argv[])
{
    /* code */
    base obj(10,20,30);
    cout << "&obj:" << &obj << endl;
    obj.show();
    return 0;
}

四.malloc和new 的区别

C++
class base{
    public:
    base(int a){

        cout << "调用构造函数" << endl;

        this->a = a;
    }
    void show(){
        cout << a << endl;
    }

    private:
    int a;
};

int main(int argc, char const *argv[])
{
    // 使用malloc 从堆空间分配内存 给base
    // 不会自动调用base的构造函数
    // 导致类中的成员a 无法被初始化
    // base * p = (base *) malloc(sizeof(base));
    // p->show();   //因为p是指针 所以使用->

    //===========================
    // 可以使用new关键字申请内存
    // new会自动调用构造函数
    base *p = new base(10010);
    p->show();
    return 0;
}

malloc 和 new 的区别:

  • 使用方式。“new”是C++的语言特性,是一个操作符,使用时无需指定内存大小,编译器会根据类型信息自动计算;而“malloc”是C语言中的库函数,使用时需要显式地指出所需内存的尺寸。----new自动计算大小
  • 返回值。“new”操作符在内存分配成功后返回的是对象类型的指针,无须进行类型转换;而“malloc”分配内存成功后返回的是void指针,需要通过强制类型转换将其转换为所需的类型。 ---- new自动类型转换
  • 初始化。“new”不仅分配内存,还可以直接调用对象的构造函数进行初始化;而“malloc”仅分配内存,需要调用者自行初始化分配的内存。---- new 自动调用构造函数

五. 析构函数

析构函数特点:

1.函数名和类名相同,但需要在函数名之前加 ~ (波浪线)

2.析构函数没有返回值, 也没有参数

3.当对象被销毁时 系统自动调用析构函数(可以释放成员空间)

作用:

释放构造函数初始化的数据成员

注意:

  • 析构函数不可以重载 重载的依据是参数,而析构函数没有
  • 析构函数必须写在公共区 对象销毁自动调用

练习:

定义一个类,对数据成员进行初始化,数据成员是字符串类型 长度是1024

创建 3个对象 考虑内存泄漏的问题----必须调用析构函数

练习: 设计file类 , 在构造函数中打开文件,设计一个写入数据接口.在析构函数中关闭文件

C++
#include <iostream>
using namespace std;

extern "C"{
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <string.h>
}

//文件类
class file{
    public:
    //构造函数 -- 打开文件
    file(const char * filename = "test.txt"){
        fd = open(filename, O_RDWR | O_CREAT,0777);
        if (fd < 0)
        {
            cout << "打开文件失败~" <<endl;
        }else{
            cout << "打开文件成功~" << endl;
        }
    }

    //自定义接口-- 写入数据
    int write(const char * str = "这是默认内容,你就懒吧~"){
        // :: 使用最前面引入的头文件中声明的系统函数write
       int size = ::write(fd, str, strlen(str));
       return size;
    }

    //析构函数 -- 关闭数据
    ~file(){
        close(fd);
    }

    private:
    int fd;  //文件描述符
};
int main(int argc, char const *argv[])
{
    // //定义文件类的对象
    // file ff;
    // //写入数据
    // ff.write("今天就讲到这吧~");

    file a("my.txt");
    a.write();

    return 0;
}

六.类的大小计算

类的大小计算和结构体一样

C++
struct Node{
    int a;
    char c;
    double d;
    short s;
};
//24字节 (64位)  // 32位/64位  地址能被数据类型大小整除,
//总数据大小要能被其中的最大数据类型大小整除类的大小

class base1{
    private:
    char a;  //2

    protected:
    short b; //2

    public:
    int c;   //4
};  //大小 8


class base2{
    public:
    char a;  // 4
    void fun(){
        int m;
        float n;
        long long q;
    }

    protected:
    int b;  //4

    private:
    short c; //2 + 2
};  //大小 12

结论: 在设计类中的数据成员时, 应该将数据类型按照字节数从小到大的顺序去定义,这样定义可以节省内存,所占空间最小

注意:

类中的大小与成员属性定义顺序有关  --  从小到大

类中的大小与成员函数  --  无关!

注意:

C++
class base{

    private:
    static int sta;  //静态成员变量
    
}
//类外进行初始化
int base::sta = 789;   //静态成员变量 存储在 数据段中 不属于类内的空间中

注意: 类中的静态成员变量 ,无法在类内实现初始化,只能在类外进行初始化

七. (只用于)构造函数的参数列表初始化

C++
  base(int a1, short b1, char c1):a(a1),b(b1),c(c1)
  {
      //注意: 以上的初始化方式并不是万能的
      // 需满足一个条件: 数据类型必须支持 = 赋值
      // 例如 数组 不支持=赋值 所以不能用以上方式

      //初始化过程
      // this->a = a1;
      // this->b = b1;
      // this->c = c1;
  }

注意:

以上的初始化方式并不是万能的
需满足一个条件: 数据类型必须支持 = 赋值
例如 数组 不支持=赋值 所以不能用以上方式

练习: 要求定义一个构造函数 利用参数列表初始化的方式对数据成员进行初始化

C++
struct Node{
    int a;
    char c;
}
class base{
    private:
    int a;
    struct Node n;
    char str[100];
}

目录

一.  c++中的类(核心)

1.类的三大特征:  封装 继承 多态

2.类的定义

二. C++中的构造函数

三. this关键字

四.malloc和new 的区别

五. 析构函数

练习:

六.类的大小计算

七. (只用于)构造函数的参数列表初始化


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值