类
- 空类的大小是1。
- 在默认情况下,类中的成员(包括数据和函数)都是私有的,结构体中的成员在默认情况下都是公有的。
- 构造函数是在初始化的时候调用的,只能有一个默认构造函数,
- 静态数据成员(static)
(1)静态数据成员是类的一个成员,同一个类中所有对象共享该变量,
(2)静态数据成员不依赖对象而存在,在对象之前已经存在,类的大小计算不包括静态变量
(3)静态数据成员的生存周期和整个程序的生存期一样
(4)静态数据成员在类的内部进行说明,必须在类的外部进行定义,否则编译出错 - 静态成员函数(static)
(1)静态成员函数和静态数据成员类似,在对象生成之前已经存在。
(2)只能访问类中定义的静态成员,其他数据可以以参数形式传到静态函数中。 - 友元函数既可以是一个外部函数,也可以是另外一个类的函数成员,他可以访问类中定义的私有成员,关键字friend。
- 拷贝构造函数
- 是一个特殊的构造函数,当定义一个对象并采用同类型的另外一个对象初始化时,将自动调用拷贝构造函数。
- 拷贝构造函数的参数一定是一个引用。如果他的形参只是一个普通的局部对象,则在传参的时候又会调用拷贝构造函数,引起循环调用,直到内存耗尽。
ClassName (ClassName &obj){}
运算符重载
重载赋值运算符
ClassName operator = (const ClassName &right){……;return *this;}
注意:右边的参数不一定是常引用,引用的好处是防止传参时候生成拷贝对象,减少时间空间。
重载前置++运算符,++n
ClassName operator ++(){}
重载后置++运算符, n++
ClassName operator ++(int){}
注意:后置++运算符中参数只有类型而没有名称,是一个哑元。
重载类型转换运算符
operator float(){float temp;;return temp;}
重载流运算符(<< , >>)
friend ostream &operator <<(ostream &strm, ClassName &obj)(strm<<obj;return strm;) friend istream &operator >>(istream &strm, ClassName &obj)(strm>>obj;return strm;)
上诉函数告诉c++如何处理下列形式的表达式:
ostream_obj << ClassName_obj
注意:这两个操作符分别定义在ostream和istream类中,因此需要通过友元函数的形式实现函数重载。cout和cin分别是ostream和istream类的对象。函数的返回值之所以是一个Ostream对象,是为了处理如下级联调用形式的语句:
cout<<Class_obj1<<Class_obj2<<endl;
继承、多态和虚函数
继承是已有类的基础上创建新类,多态是指类中具有相似功能的不同函数采用同一个名称来实现。
构造函数
如果类存在继承关系,派生类必须在其初始化表里调用基类的构造函数。初始化表中调用构造函数,如下例:
B::B(int x, int y): A(x) // 在初始化表里调用A的构造函数 {…}
成员对象初始化的次序完全不受它们在初始化表中次序的影响,只由成员对象在类中声明的次序决定。这是因为类的声明是唯一的,而类的构造函数可以有多个,因此会有多个不同次序的初始化表。如果成员对象按照初始化表的次序进行构造,这将导致析构函数无法得到唯一的逆序。
定义一个子类对象,先调用基类的构造函数,再调用子类的构造函数,析构函数的调用顺序相反。- private protected public
- private成员只能被本类成员(类内)和友元访问,不能被派生类访问。
- protected成员可以被派生类访问,不能被程序其他部分访问。
- public继承:基类public成员,protected成员访问属性在派生类中分别变成:public, protected,private
- protected继承:基类public成员,protected成员的访问属性在派生类中分别变成:protected, protected,基类的privilege成员不能再子类中访问
- private继承:基类public成员,protected成员的访问属性在派生类中分别变成:private, private, private
- 如果省略了继承修饰符,那么就是私有继承
- 指向基类的指针
- 指向基类对象的指针可以指向其子类对象,但基类指针指向子类对象时,所访问的任然是基类中的成员。
- 如果子类覆盖了基类的成员(函数成员或变量),但通过该基类指针所访问的成员任然是基类成员,而不是子类成员
- 反过来不行,指向子类对象的指针不能指向基类对象。
重载、覆盖(重写)、隐藏区别
- 重载, 参数不同的同名函数,不关心返回值。并不是两个函数的名字相同就能构成重载。全局函数和类的成员函数同名不算重载,因为函数的作用域不同。对于函数重载,out(float a)和out( int a) 当调用 out(1)时,是正确的, 当调用out(0.5)时,编译错误,因为编译器无法确定应该如何进行类型转换。
- 隐藏, 是指派生类的函数屏蔽了与其同名的基类函数,注意只要同名函数,不管参数列表是否相同,基类函数都会被隐藏。
- 覆盖, 重写的基类中被重写的函数必须有virtual修饰,覆盖是c++多态的部分体现。
- 函数重载只是动态的多态性,在编译阶段,给不同的函数不同的函数名,而虚函数实现运行时多态。
- 虚函数是c++多态的真正体现
虚函数,纯虚函数
- 虚函数是一个成员函数,唯一要求是子类中一定要覆盖他。对于虚函数,编译器完成的是动态绑定,即对函数的调用是在运行时确定的。这样在调用父类的方法时,该方法中的函数调用是动态的,即会调用子类中重写的函数,而不是父类中的函数。
- 纯虚函数在基类中没有函数体,要求在子类中一定要覆盖它。有纯虚函数的类称为抽象类,不能定义对象。
模板,类模板
常用结构体
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
/*****************************
Definition for an interval.
******************************/
struct Interval {
int start;
int end;
Interval() : start(0), end(0) {}
Interval(int s, int e) : start(s), end(e) {}
};
/*****************************************
Definition for a binary tree node.
******************************************/
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};