基础知识点
-
C++中对象数组在定义的时候全部进行实例化(与Java不同,Java相当于只是定义了一个指针数组,没有进行实例化)
-
程序的三种基本控制结构是:顺序结构、循环结构、选择结构
-
一个C++程序开发步骤通常包括:编辑、编译、链接、运行和调试
-
面向对象程序设计主要有四个特点:抽象、继承、多态、封装
-
C++中的两种代码复用方式:继承和模板
-
类是某一类对象的抽象,对象是类的具体实例,类和对象的关系是一种数据类型与变量的关系
-
构造函数的作用是再创建对象的时候初始化对象的数据成员
-
默认构造函数有两种:无参构造函数和所有参数都有默认值的构造函数(两者不能同时存在)
-
常对象只能调用它的常成员函数,不能调用普通函数
-
如果一个类没有定义默认构造函数,但是定义了其他构造函数(有参的),编译器将不会自动生成默认构造函数(此时如果派生类中没有显式调用父类的有参构造函数将会编译出错)
-
cin
是istream
类的对象 -
转换构造函数只有一个参数,可以隐式地将其他类型转换成该类类型。可以用
explicit
杜绝编译器的隐式转换。与之对应的还有类型转换函数,可以将类类型转换成其他类型。详见:C++转换构造函数和类型转换函数 -
析构函数的作用是提供一个在对象删除前释放该对象占用资源的机会
-
构造函数顺序和析构函数相反
-
构造函数顺序:虚基类->普通基类->成员对象->当前类详见:C++派生类含有成员对象构造函数析构函数顺序
-
拷贝构造函数的使用:
- 复制对象把它作为参数传递给函数
- 复制对象从函数返回这个对象
- 初始化另一个对象(必须是定义的时候,赋值不算)
-
重载和函数的返回值没有关系,只和函数名以及函数参数列表有关。派生类中只要函数名字和基类相同就会重写。重写以后我们将无法直接通过派生类对象访问基类的同名函数,只能通过
基类名::
显式访问 -
需要注意保护的成员我们也不可以通过对象访问
-
this指针:在每一个非静态成员函数中都包含一个特殊的指针,这个指针的名字是固定的,称为
this
指针。他是指向本类对象的指针,他的值是当前被调用的成员函数所在对象的起始地址。这样同一个类创建的多个对象共用同一份成员函数的拷贝也知道是取哪一个对象的成员数据。如果派生类中含有和基类相同名字的成员函数就会重写 -
要实现动态联编一般通过对象指针调用虚函数
-
在C++面向对象程序设计框架中类是程序的基本组成单位
-
delete
只能释放用new
运算符分配的内存 -
静态数据成员只能在类外定义和初始化,格式为
数据类型 类名::变量名=初值;
不需要
static
关键字 -
编译器自动生成的拷贝构造函数可能会产生什么问题:当对象有指针数据成员,并用它初始化同类型的另一个对象时,缺省的拷贝构造函数只能将对象的数据成员赋值赋给另一个对象,而布恩那个将该对象中指针所指向的内存单元也复制一份。这样就可能出现同一内存单元释放两次,或者传递参数后实参中的地址无效,导致程序运行出错。
-
使用虚基类是为了解决多重继承中的二义性问题
-
静态函数没有
this
指针 -
描述友元函数的时候应该说明是哪个类的友元函数
-
拷贝构造函数同样是构造函数,因此和构造函数的调用顺序一样,调用顺序为虚基类->基类->成员对象->拷贝构造函数。
#include<iostream>
#include<string>using namespace std;class A
{int val;
public:A(){val = 0; cout << "A():" << val << endl;}A(int v){val = v; cout << "A():" << val << endl;}
};class B :public A
{A obj;
public:B(int v1, int v2) :A(v1), obj(v2){cout << "B()" << endl;}B(const B& x){cout << "Copy B()" << endl;}
};int main()
{B obj1(2, 3);B obj2(obj1);
}
运行结果:
- 结构化的程序设计与面向对象的程序设计:结构化的程序设计将数据和对数据的操作分离,程序是由一个个函数组成的。面向对象的程序设计将数据和操作封装在一起,程序是由一个个对象组成的,对象之间通过接口进行通信,它能够较好地支持程序代码的复用。
- 类和结构体都是C++中用户自定义的数据类型。
- 从实现的角度来讲,多态性可以划分为两类:静态多态性、动态多态性
虚函数
- 不能声明为虚函数的函数:普通函数、构造函数、静态函数、内联成员函数、友元函数。成为虚函数的特点是:可以被重写/重载,可以在运行时才确定。详见:C++不能被声明为虚函数
- 虚函数用于实现动态多态性
- 纯虚函数实在基类中说明的虚函数,它在该基类中没有定义具体的操作内容。含有纯虚函数的类称为抽象类,抽象类不能被实例化(可以定义指针和引用),必须由他的派生类完成对纯虚函数的定义
友元函数
- 友元函数不是成员函数,破环隐蔽性,尽量减少使用。友元函数可以提高程序运行效率,节约了调用类成员函数的开销
运算符重载
- 不能进行重载的运算符:
.
成员访问运算符.* ->*
成员指针访问运算符::
域运算符?:
条件运算符#
预处理运算符,详见:【C++学习笔记四】运算符重载 - 运算符重载以后,要求其保持原来的操作数个数、优先级、结合性、语法结构
- 后缀自增运算符的第一个参数(如果还有其他参数的话)必须是
int
,这样做是为了区分前缀和后缀 - 运算符函数可以重载为成员函数、友元函数和普通函数。但是有的运算符只能重载为成员函数:
= [] () ->
模板
- 类模板的使用是将上是将类模板实例化成一个类
- 对于模板类我们只有要用到的时候才会进行实例化:
- 模板类作为函数声明的参数不会实例化
- 定义模板类的指针和引用不会实例化
- 但是如果进行定义时(其他类中含有模板类成员、函数参数或者函数体中含有模板类)以及模板类指针需要访问成员时都会进行实例化。
- 需要知道模板类大小的操作都需要进行实例化。如
new sizeof
运算符等。详见:C++类模板实例化条件
继承、基类指针指向派生类对象
- 私有继承不允许基类指针指向派生类
- 基类指针只能访问到基类中含有的公有成员
- 当用基类指针指向派生类对象在动态分配堆上内存的时候,析构函数必须是虚函数
详见:C++基类指针指向派生类(指针)
流输入流输出
- 重载流插入运算符
<<
重载流提取运算符>>
cin
是istream
的对象,cout
是ostream
的对象
const的用法
可以阅读这个博客,已经将的超级详细了:传送门