C++ 类(1)

1.什么是类

在C语言中,我们学过结构体,我们可以在结构体里面定义变量

在C++中,我们还可以在结构体里面定义函数

struct Add
{
    int a;
    char b;
    double c;
    int& cal(int a, int b)
    {
        a = a + b;
        return a;
    }
   };
    int main(void)
    {
        struct Add s1;
        int a = 3;
        int b = 4;
        printf("%d\n", s1.cal(a, b));
        return 0;
 }

但是像上面这种结构体,在C++中,更喜欢用class来代替,class就算类

class Add
{
    int a;
    char b;
    double c;
public:  void cal(int a, int b)
    {
        a = a + b;
        printf("%d\n", a);
    }
   };
    int main(void)
    {
        class Add s1;
        int a = 3;
        int b = 4;
        s1.cal(a, b);
        return 0;
 }

细心的人看出来了,除了把struct换成class以外,上面还加了一个public,不加这个public编译就通过不了,我们先来解释一下,什么是public

2.限定符

public是访问限定符

访问限定符有三个 public protected private 

我们学C++初阶可以理解成protected 和 private是一样的,只有到继承多态那可能才会有差别

1.public修饰的成员在类外可以直接被访问
2. protected和private修饰的成员在类外不能直接被访问

3.访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止
4.如果后面没有访问限定符,作用域就到}即类结束。
5. class的默认访问权限为private,struct为public(因为struct要兼容C)
注意:访问限定符只在编译时有用,当数据映射到内存后,没有任何访问限定符上的区别

C++需要兼容C语言,所以C++中struct可以当成结构体使用。另外C++中struct还可以用来定义类。和class定义类是一样的,区别是struct定义的类默认访问权限是public,class定义的类默认访问权限是private。

这也就能解释了为啥class要额外加一个public了,同样,如果你不想struct里面的函数直接在类外被访问,那么就可以一样去加一个private或者protected

那么我们再来思考一件事,就算结构体有内存对齐,那么类怎么计算大小呢?

同样的类也有结构体对齐的特性,因为在C++中,不管是结构体还是类,其内存模板基本都是相同的

3.类的内存

但是类在计算大小中不会把函数的内存大小算进去

为什么?

class Add
{
    int a;
    char b;
    double c;
public:  void cal(int a, int b)
    {
        a = a + b;
        printf("%d\n", a);
    }
   };
    int main(void)
    {
        class Add s1;
        class Add s2;
        return 0;
 }

我们看这个s1和s2,它们的结构体成员可能不同,但是它们的结构体里面的函数是不是一样了,

既然是一样的,我完全没必要每次创建一个类再去专门创建一个地方存放函数,因此函数是被存放到一块公共区域,所以类的内存大小和其中的函数无关

因此

int main(void)
{
    int a = 1;
    int b = 2;
    Add s1;
    s1._a = 1;//去类里面找_a赋值
    s1.caa(a, b);//去公共区域里面找caa函数调用
    return 0;
}

4.类的声明和定义

我们再来思考第二个问题,类里面的函数可以声明和定义分离吗?

直接使用是不行的,编译器怎么知道这个cal函数是哪的cal函数 ,是哪的函数

想改也很简单,让编译器知道是哪里的函数就可以了(指定类域),也就是把aaa.cpp那个文件的函数改成

void Add::cal(int a, int b)
 {
     a = a + b;
     printf("%d\n", a);
 }

此外,在类里面定义的函数默认是内联函数,也就是在类里面的函数不管你加不加inline,都默认是内联函数。当然如果那个函数太长了,编译器也不会把它当作内联函数

那么再思考,下面这个代码

class Add
{
public:
    int a;
    char b;
    double c;
    void caa(int a, int b)
    {
        a = a;
    }
};

这个a是类的成员的a还是参数a

这个函数内是局部域,所以是局部域的a而不是类域成员的a

但是为了好区分,一搬都会对类的成员做一些标记比如下面这样

class Add
{
public:
    int _a;
    char _b;
    double _c;
    void caa(int a, int b)
    {
        a = a;
    }
};

5.封装

此外,类还有一个作用是封装,比如在顺序表那块,c语言的成员和方法(函数)是分开的,有的人使用比较流氓,不用函数,而是直接改capacity和size的值,
 

c++这个地方规范了很多,我不想让它直接改这些数据,只想让他规规矩矩的用函数去改,这个时候就可以用类了,类的成员是private,我们只用给函数public不给类的成员就可以了!

此外,向上面这个类(Add),需要注意,

 Add::_a = 1;

这样是错误的,因为Add只是声明,没有去开辟空间

应该这样写


    Add s1;
    s1._a = 1;

上一篇:数据仓库宽表概述-四、宽表的应用场景


下一篇:10个关于Yolo-v5神经网络的论文的创新点