C++知识点复习(面向面试2)
今天复习的知识点有五条,都相对简单,但我们还是都从原理到底层剖析,方便大家查漏补缺,如果有错误,也请大家指正。
6.构造函数
7.析构函数
8.拷贝构造
9.const
10.static
好的,我们从第六条开始。
6.构造函数
构造函数是什么,简单来说就是对象的出厂设置,是为了给变量赋值而不是初始化。构造函数有三个核心特征,第一,函数名和类名完全相同。第二,绝对没有返回值。第三,对象创建时自动调用,不能手动调用。
构造函数分为三大类,无参构造函数,有参构造函数,拷贝构造函数。其中,如果你没有写任何构造函数的时候,编译器会自动生成一个无参构造函数,但如果你已经写了有参,就不会自动生成,必须手动书写。有参构造函数,带参数的,在创建对象的时候会直接传入初始值。最后的拷贝构造函数我们聊完const再来细说。
在聊到构造函数是为变量赋值而不是初始化的时候可以向面试官引出初始化列表,这也是一个高频考点。
class A { int *p = nullptr; public: A(int n) //实现了构造函数编译器不提供默认的无参构造 { if (n > 0) p = new int[n]; //在堆区分配内存 n 个 int 类型的数据 } ~A() { if (p) delete[]p; // 注意释放数组时 一定要加上[],否则只会释放数组的第一个 元素,造成内存泄露 } };修改实参。
// 1. const 在 * 左边:指向常量的指针 const int* p1 = &a; // 等同于 int const* p1 *p1 = 30; // 报错!不能通过 p1 修改 a 的值 p1 = &b; // 合法!指针本身的指向可以随便改 // 2. const 在 * 右边:常量指针 int* const p2 = &a; *p2 = 30; // 合法!可以通过 p2 修改 a 的值 p2 = &b; // 报错!p2 一旦初始化,就“从一而终”,不能再指向别处 // 3. const 在 * 两边:指向常量的常量指针 const int* const p3 = &a; *p3 = 30; // 报错!不能改指向的值 p3 = &b; // 报错!不能改指针的指向const 在 * 左边:修饰的是指向的内容(底层 const),表示“不能通过指针去修改指向的值”。
const 在 * 右边:修饰的是指针本身(顶层 const),表示“指针的指向不能变”。
3.const修饰函数时,表示常函数
在类的成员函数后面加上 const,表示这个函数是一个“只读函数”,它承诺绝对不会修改类里的任何成员变量。
const 修饰函数时,表示常函数
(1).常函数内的this指针在vs中是 const type * this;(type代表类型),所以常函数内不能修改成员变量,也不能调用非常函数(因为 this 指针再传递的时候类型不匹配)。
(2).常对象只能调用常函数,非常对象既可以调用常函数也可以调用非常函数。
(3).常函数和非常函数是重载关系因为 this 类型不同(可以引导说 this 是怎么来的)。
4.const 修饰变量时表示变量不可以修改,但是可以通过指针来修改,代码如下:
const int a = 2; const int *p = &a; //首先将 p 从 const 类型的指针转换成非 const int* p1 = const_cast<int*>(p); //const_cast 这里可以看看 C++11 的四种强制类型转换 *p1 = 3; cout<<*p<<" "<<*p1<<endl;static 修饰全局变量时:
如果没有初始化,编译器会自动初始化为 0,生存周期和全局变量和程序一致,只能在当前文件访问,如果想在头文件中定义全局变量,那么需要定义成静态全局变量,因为如果多个cpp 文件引入同一个头文件那么会导致多个 cpp 文件中有相同的全局变量,如果没有定义为static 会导致重定义问题。
void fun() { static int a = 1; a++; cout<<a<<endl; } int main() { fun(); fun(); }运行结果是2 3。static int a 存储在静态存储区。它在程序启动时就被创建,直到整个程序运行结束才会被销毁。
static 修饰成员变量时:
static 修饰成员函数时:
静态成员函数没有 this 指针因此静态成员函数不能访问非静态成员变量(原因:无法区分是哪个对象的成员变量),静态成员函数不能调用非静态成员函数,因为非静态成员函数有隐含参数 this,因为静态成员函数无法给非静态成员函数的 this 传值,静态成员函数可以调用静态成员变量因为静态成员变量时共享的不需要使用 this 来区分是哪个对象的,也可以调用静态成员函数,因为静态成员函数不需要给 this 传值。
这是今天所有的知识点,做好查漏补缺,我们明天见!
