数据类型:struct、union、enum。
初始化: int x(1024)[直接初始化]
命名空间作用:区分相同的变量名。
定义命名空间:
namespace A{
int x=0;
bool b = true;
void f1();
}
namespace B{
int x=0;
bool c=false;
void f1();
}
cout << A::x << " " << B::c << endl;
引用:别名, int &b =a;
typedef AAA{
int x=0;
}BBBB;
// BBBB 是AAA结构体的引用。
void swap(int &a, int &b){
int c = a;
a=b;
b=c;
}
const: 常量
const int *p =NULL; /*===*/ int const *p = NULL; // *p不可改
int * const p = NULL; // p 不可改
函数重载: 编译之后,采用函数名和参数类型形成一个新的函数名,调用的时候使用自动识别。
内联函数 inline:普通函数在编译时寻找函数的入口,然后执行函数。而内联函数则在编译是就用函数体覆盖了函数调用的语句。是不是内联由编译器决定。
内存的申请和释放:new 和 delete。
int *p = new int;
delete p;
int *p = new int[20];
delete []p;
// 实际应用: 判断内存是否申请成功!!!
int *p = new int[10];
if(p == NULL){
// 内存申请失败
}
// 在释放内存后 需要把指针置空!!!
delete []p;
p = NULL;
对象的实例化:栈中实例化(函数的里的局部变量声明,就是在栈中申请内存)、堆中实例化(使用指针申请,是在堆中申请的内存)。
内存分区: [课程:封装篇上 6-1]
- 栈区:int x=0; int *p=NULL;
- 堆区:int *p=new int[20];
- 全局区:存储全局变量和静态变量
- 常量区:string str=”hello”;
- 代码区:存储逻辑代码的二进制
初始化列表:Student():age(10),name(“wy”) {},先于构造函数执行。
拷贝构造函数。
每个对象有自己的成员变量,但是会共享类里面的成员函数。使用this指针区分不同的对象。
const修饰成员函数,函数内不能修改成员变量的值。可以和非常成员函数同名,当对象是常对象时,调用const修饰的重载函数。反之则调用非const的成员函数。
继承: 覆盖 <——>隐藏
-
隐藏
- B继承A,都有一个名为ABC()的函数,创建B类对象都用的ABC()函数,就是B类的ABC函数。如果想访问父类的函数:b.A::ABC()。
子类可以赋值给父类,父类不能赋值给子类。 父类=子类; 父类指针=子类对象
虚继承: class B: virtual public A,解决菱形继承问题。
静态多态(早绑定):就是在类里面的函数重载。
动态多态(晚绑定):继承,封装。B继承A,C继承A,ABC类里都有abc()函数,当使用A类的指针指向子类时,如果想调用子类的abc()函数,则需要在三个类里面的abc()函数前加virtual关键字。
虚析构函数:使用virtual修饰,当父类指针指向子类时,删除父类指针时不会调用子类的析构函数,使用virtual修饰则先调用子类的析构函数,然后调用父类的析构函数。解决内存泄漏问题。
virtual:不能修饰普通函数,只能修饰成员函数。不能修饰静态函数,不能修饰内联函数。不能修饰构造函数。
函数指针,
-
多态的原理:
- 如果类里面有虚函数,在存数据成员的同时会有一个 虚函数表指针 ,指向一个虚函数表,虚函数表里存的是虚函数的入口地址。指针的位置在对象的第一个内存地址。
如果子类没有定义和父类同名虚函数,则子类的指针执行的是父类函数,如果定义了同名虚函数 ,则指向了子类的函数入口地址,这就是覆盖。
纯虚函数: virtual void func()=0; 纯虚函数在虚函数表的值是0
含有纯虚函数的类叫抽象类。抽象类无法实例对象。
仅含有纯虚函数的类就是接口类。
RTTI : 运行时类型识别。
判断是否是相同的类型:typeid (*p) == typeid(CLASSNAME)
-
dynamic_case注意事项:
- 只能用于指针和引用的转换。要转换的类型必须含有虚函数。转换成功返回子类型的地址,失败返回NULL。 typeid注意事项:
- type_id返回一个type_info对象引用。如果想通过基类的指针获得派生类的数据类型,基类必须带有虚函数。只能获取对象的实际类型。
try{
// do some thing and throw ...
}
catch(Exception &e){
// e->print();
}
catch (...){
// all kinds of exception
}
友元函数: friend void function(Class &A); 函数的参数必须是类型的引用或者是类的指针,能通过它访问类的私有和保护的数据成员。
友元成员函数:
class B{
// friend void func(B &b);
friend void A::func(B &b);
public:
B();
private:
int x;
int y;
}
友元类:
class A;
class B{
friend A;
public:
B();
private:
int x;
int y;
}
A可以建立B的对象, 并可以访问B的私有数据成员和函数。
友元不能传递,友元关系是单向的。
静态数据成员,在类的外部初始化,不能在构造函数中初始化。
静态的函数只能调用静态的函数和数据成员,非静态都能调用。
运算符的重载:友元函数的重载,成员函数的重载。
class A{
// friend A& operator-(A &a);
public:
A& operator -();
A& operator ++(); // 前置重载
A operator ++(int); // 后置重载,参数是为了标识是后置重载
A operator +(const A &a){
// do add operator
return temp;
}
}
A& A::operator -(){
// do something;
return *this;
}
// typename 和class 作用一样
template<class T> // template <typename T, typename C>
T max(T a, T b){
return (a>b)?a:b;
}
template<typename T, int size>
void dis(T t){
cout << size <<endl;
cout << t<<endl;
}