我们C++面向对象的三个重要内容就是:封装,继承和多态,今天我们就浅谈一下封装的概念。
C++的封装,实现方式就是用 class 关键字来声明类。在类中,成员变量叫做属性,成员函数叫做方法。
1、类的访问控制:
public :共有属性,类的内部外部都可访问
private:私有属性,类的外部禁止访问
protect:保护属性,用于继承中,类内部专属
当我们没有标明是private 属性 ,在结构体中,是默认共有的,而在类中,是默认私有的。
2、构造函数:用来对类的成员进行初始化,它没有返回值,函数名与类名一致,在定义对象时自己被调用。
该函数是可以被重载的(根据对象的定义方式不同),由此我们可以判断对象的定义方式有:
1)直接定义对象(括号法):
2)等号方式:Test t1(10); Test t2(10); Test t3(10,20); //分别调用了无参构造,1个参数和2个参数的构造函数
3)手动调用构造函数:Test t4 = 10; Test t5 = (10,20); Test t6 = t4; // 这种方式只能定义单个参数的构造函数,t6是拷贝构造
Test t7 = Test(); // 手动写出构造函数的参数形式
3、析构函数:无返回值,无参数,无法手动调用,在对象销毁前会自动被调用
编写方式就是类名前加上 ' ~ ' 符,通常用来销毁开辟的空间,防止内存泄漏。
4、拷贝构造:单独拿出来说就说明它很重要(虽然我们写程序的时候要尽量避免使用它)
函数名就是上面这种方式,它的几种调用方式:Test (const Test& obj){};
1)首先,直接初始化,用上面提到的括号和等号的方式来调用;
2)当对象作为函数参数传递的时候会调用拷贝构造;
3)当函数的返回值是一个对象时;void test(Test t) // 这边就自动调用了拷贝构造 { t.print(); }
Test test() { Test t(10); return t; // 这边自动调用了拷贝构造
一个函数返回一个对象的时候会创建一个匿名对象,拿返回的那个对象对匿名对象进行初始化,会调用拷贝构造,如果没有去接收函数的返回值的话,匿名对象会立马被销毁;如果用一个对象去接收函数的返回值,先用函数返回的对象去初始化匿名对象,调用一次拷贝构造,然后拿新的对象的名字去命名这个匿名对象,匿名对象从无名变有名。}
5、默认构造函数:如果类中没有定义任何的构造函数,编译器会自动生成一个空的无参构造函数,但如果写了任何形式的构造函数,便不再生成。
同样,如果没有定义拷贝构造和析构函数,也会自动生成一个普通的拷贝构造函数和空的析构函数;
6、浅拷贝:在拷贝指针时只是拷贝地址,不进行空间复制,这样在调用析构函数时,同一块空间会被释放(delete)2次,造成程序奔溃。
深拷贝:这时就需要我们自己编写构造函数,在拷贝时,需要另外开辟空间(new);
但通常,为了安全我们都需要拒绝拷贝构造函数,可以将其设为私有(只需声明),和次类似的,类的赋值操作通常也是拒绝的(日后会提到);这里要提一下,构造函数也是可以被设为私有的,这样就不能在外面进行类的定义了,但析构函数不能被设为私有。
7、对象初始化列表:解决了 一个类中 有 另外一个没有无参构造的类的 对象的初始化问题。
在构造函数后面加上 ' : ' 后面加初始化对象就好,对象的初始化顺序只和类中声明的先后顺序有关;
对象初始化列表也可以用来对常量进行初始化。
8、构造函数中调用构造函数
么有任何效果,类似于直接产生匿名/临时对象,因为调用了2次析构函数。
Test(int a, int b) { m_a = a; m_b = b; Test(a, b, 30); // 匿名对象、临时对象 }
9、静态成员变量和静态函数
1)静态成员函数属于类,它只有一个备份,但所有的对象都能使用(类似于多进程中的共享内存)。它必须在类的外部重新定义并初始化。变量使用方法:
2)静态函数的使用方式同上,但它只能使用静态成员变量。t.sm_a = 20; // 通过某一对象 Test::sm_a = 30; // 通过类名
10、对象的动态创建与释放:malloc 、free 与 new、delete
malloc 和 free 并不是C语言的一部分,它们是库函数提供的函数,而 new 和 delete 是C++的一部分,它们是运算符而不是函数(可以被重载)
new 和 delete 在创建和释放对象时会自动调用构造和析构函数
new 和 delete 的使用:
1)new + 数据类型,返回值是指定类型的指针;delete + 该指针
2)直接初始化:int *p1 = new int ; delete p1;
3) 申请与释放数组:用[ ] ,delete后面加上[ ] 即释放数组int *p2 = new int (10); delete p2;
int *p3 = new int [10]; delete [] p3;
11、对象模型:即结构体
建类时调用函数 ==> 传递了一个指针(this->)
C++的类的成员方法中存在这样一个 this 指针,用来指向当前对象。
静态成员变量存在全局数据域中,静态成员函数没有 this 指针。
12、成员函数与全局函数的转换:
1)全局转成员可以通过this指针来隐藏左操作数
2)成员转全局则是将隐藏的左操作数(Tset *this)写出来
13、友元函数: friend关键字用来声明友元函数,被声明的函数可访问该类的私有变量1)在类中只有声明,它不是类的内部函数,需要在外部实现
2)友元函数的声明不受类的访问限制,可以在任意位置(一般写在最开头)
3)友元函数破坏了类的封装性
友元类:
在友元类中的所有函数都是该类的友元函数。
友元类需要在该类之前作声明。