(1)数组大小不能动态定义:
//int a[i];//不合法 //定义数组大小的常量表达式不能是变量
int a[] = {1,2,3};
int a[3] = {1,2,3};
int a[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};
int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
int a[3][4] = {1,2,3,4};//相当于给第一行赋值,其余数组元素全为0
数组赋值方式:单个元素逐一赋值、聚合方式赋值。
(2)聚合方式赋值只能在数组声明时使用:
char pW[5];
//pW = {'H','E','L','L','O'};//错误
字符数组不能给字符数组赋值:
char a[5] = {'H','E','L','L','O'};
char b[5];
//a = b;//错误
a[0] = b[0];//正确
(3)作为字符串要有字符串结束符“\0
”,可以使用字符串为字符数组赋值:
char a[] = "HELLO WORLD";
//等同于
char a[] = "HELLO WORLD\0";
字符串结束符“\0
”告知字符串处理函数字符串已经结束了。
(4)strlen(字符数组名)
测量字符串实际长度(不包括“\0”);strcat(字符数组名1, 字符数组名2)
将字符数组2的字符串连接到字符数组1中字符串的后面,并删去字符串1后的“\0”;strcpy(字符数组1, 字符数组2)
将字符数组2中的字符串复制到字符数组1中,“\0”也一同复制;strcmp(字符数组1, 字符数组2)
按照ASCII码顺序比较两个数组中的字符串,由返回值返回比较结果(字符1>字符2返回正数,字符1<字符2返回负数,字符1=字符2返回0)。
(5)标准输入流cin
和格式化输入函数scanf
都存在这个问题:当输入空格时,输入的对象不会接受空格符之后的内容;
输入函数gets
和输出函数puts
都只以结束符“\0
”为输入\输出结束的标志。
(6)指针变量是存放地址的变量,如果把数组的地址赋给指针变量,就可以通过指针变量来引用数组。如果指针变量p已经指向数组中的一个元素,则p+1指向同一数组中的下一个元素。
(7)在数组声明之后,C++分配给了数组一个常指针,始终指向数组的第一个元素——数组名其实是一个指针常量;
用a+i
表示数组a中的第i个元素,然后通过指针运算符就可以获得数组元素的值:
cout << *(a + i) << endl;
(8)对于二维数组:
int *p;
p = a;//p指向a的首地址
p = &a[m][n];//第m行第n列元素的地址
/*
&a[n]是第n行的首地址;
a[0] + n表示第0行第n个元素的地址;
*(*(a + n) + m)表示第n行第m列元素;
*(a[n] + m)表示第n行第m列元素;
*/
(9)main(int argc, char *argv[])
中argc
是获取命令参数的个数,argv
是字符指针数组,可以获取具体的命令参数。
(10)
int *p[];//指针数组;是一个元素全为指针的数组
int (*p)[];//数组指针;可以直接理解是指针,只是这个指针类型不是int也不是char而是 int [4]类型的数组
int (*p)[4];//表示一个内存空间,这个空间用来存放一个指针,这个指针指向一个长度为4、类型为int的数组
(11)本地字符串类型string
string s1("字符串");
string s2 = "字符串";
string s3 = (3, 'A');//s3的内容为AAA
使用+
号可以将两个string
字符串连接起来。
string与字符串数组都可以表示一段字符串,区别:
类别不同;
字符串数组需要防范越界、结束符等问题,string不需要;
字符串可以通过地址的形式通过“=”赋值给string,但string不能直接赋值给字符串数组。
s = &aArray[2];//输出的s为字符串数组aArray[2]开始之后的所有字符串
(12)面向对象三大特点:封装、继承和多态。
多态性:不同的对象,收到同一消息可以产生不同的效果,这种现象称为多态性。
(13)类的数据成员不可以在类的声明中初始化。
构造函数可以有参数,通过外部数据完成对象内部的初始化:
class CPerson{
public:
CPerson();
~CPerson();
private:
int a;
};
//构造函数初始化
CPerson::Cperson(int a_){
int a = a_;
}
//创建对象时
CPerson p(0);//调用带参数的构造函数
(14)在每个类的成员函数中都隐含包含一个this
指针,指向被调用对象的指针,在函数调用时将对象自身的地址隐含作为实际参数传递。
(15)const
对象必须初始化,是一个只读对象,不可修改。
(16)数组是通过指针分配到的一段额定大小的内存空间,可以包含对象。
可以通过对象指针申请动态对象数组:
int n;
box *pbox;
pbox = new box[n];//n为整数
(17)string
类支持使用加号“+”连接两个string对象,但是使用两个string对象相减却是非法的。
(18)operator
是C++的重载操作符关键字,其作用就是对操作符重新定义,使其能够适应其他不同数据类型的运算。
返回值类型 operator 重载的运算符 (参数列表)
比如,“+”本来是算术运算符,一般用于基本数据类型,但是想要运算用户定义的数据类型class(在class可能会含有多种数据类型),这时候用重载运算符就可以将两个对象进行操作。
//声明
mycomplex operator + (mycomplex &p1,mycomplex &p2);
//定义
mycomplex operator + (mycomplex &p1,mycomplex &p2)
{
mycomplex p;
p.x=p1.x+p2.x;
p.y=p2.y+p1.y;
return p;
}
//调用
int main()
{
mycomplex p1(8,2),p2(8,1);
mycomplex p3;
p3=p1+p2;
std::cout<<p3<<std::endl;
return 0;
}
同理,比较运算符、逻辑运算符、位运算符、赋值运算符、调用运算符等也都可以被用作重载。
(19)类继承:
class 派生类名标识符 : [继承方式] 基类名标识符
{
派生类新增加的成员声明;
}
如果在子类中定义了一个与父类同名的成员函数,这时称:子类隐藏了父类的成员函数,此时父类中所有的同名成员函数(重载的函数)都被隐藏。子类对象会调用子类中的成员函数,如果想访问父类的成员函数,需要显示的使用父类名。
(20)继承方式有三种派生类型:
共有型(public):基类的public成员和protected成员的访问属性保持不变、基类的private成员在派生类中仍然是private,基类的私有成员不可见。
保护型(protected):基类的public成员和protected成员成为protected成员,只能被派生类的成员函数直接访问,基类的私有成员不可见。
私有型(private):基类的public成员和protected成员成为private成员,只能被派生类的成员函数直接访问,基类的私有成员不可见。
利用using
关键字可以改变基类成员再派生类中的访问权限;using只能修改基类中public和protected成员的访问权限。
//基类
class Base
{
//类外可访问
public:
Base(char name[]);//带参的构造函数
void show();
//类内访问//派生类可见
protected:
int aa;
double dd;
//类内访问
private:
};
void Base::show(){
}
//派生类
class Person : public Base
{
public:
Person(char name[]) : Base(name);//父类只有带参数的构造函数,子类必须以显示的方法调用父类带参数的构造函数
using Base::aa;//将基类的protected成员变成public
using Base::dd;//将基类的protected成员变成public
private:
using Base::show;//将基类的public成员变成private
string name;
};
如果类定义时不加关键字,默认为private
。
构造函数先父类后子类,析构函数先子类后父类。
继承中父类的析构函数要是虚函数,前面加关键字virtual
,否则会导致子类的析构函数不被调用,对象不能被正确释放,引起内存泄漏。
(21)嵌套类:通常外围类不可以访问嵌套类的私有成员,但可以通过在嵌套类内声明外围类为自己的友元类(在前面加关键字friend
),使得外围类能够访问嵌套类的私有成员。
(22)C++允许子类从多个父类继承共有的和受保护的成员,这被称为多重继承。
多个父类中有同名函数,派生类调用时会产生二义性,编译错误,解决该问题要在该成员函数前指定具体类名。
多重继承中的基类构造函数被调用的顺序是按照基类名标识符的前后顺序进行的。
(23)多态性是指不同功能的函数可以用同一个函数名,可以用同一个函数名调用不同内容的函数,发出同样的消息被不同类型的对象接收时,导致完全不同的行为。(同样的消息被不同类型的对象接收产生不同的行为)。一个接口多种实现。
多态性通过联编实现,分为静态联编和动态联编。两种类型多态性:函数重载(静态的多态)和虚函数(动态的多态)。
多态作用:代码重用(模块化)、接口重用(确保属性的正确调用)。
(24)C++的多态性用一句话概括就是:在基类的函数前加上virtual关键字,在派生类中重写该函数,运行时将会根据对象的实际类型来调用相应的函数。如果对象类型是派生类,就调用派生类的函数;如果对象类型是基类,就调用基类的函数。
(25)动态绑定实现方法:定义一个指向基类对象的指针变量,并使它指向同一类族中需要调用该函数的对象,通过该指针变量调用此虚函数。
(26)静态成员函数、内联函数、构造函数不能是虚函数;析构函数通常是虚函数。
(27)虚继承。
(28)包含有纯虚函数(带virtual
但不具体实现)的类称为抽象类,一个抽象类至少具有一个纯虚函数,且不能实例化。
只有在派生类中给出了基类中所有纯虚函数的实现时,该派生类才不再成为抽象类。
(29)友元函数/友元类可以对私有成员进行访问。