类是C++独有的,同样public也是,
类声明的时候不占内存,定义对象的时候对象占内存,编译后也不占空间,通常会把类的声明放在头文件中,把类的定义放在具体的文件中
类声明时最后有一个分号
类的成员?分成成员变量和成员函数,它们可以在类内定义,也可以在类外定义
成员变量,如果时用new分配堆空间,就要在析构函数中用delete释放空间
成员变量以m_开头
成员函数,类内定义默认时inline函数,推荐在类外定义
类外定义时用到::这个运算符,叫做域解析符,这个运算符不能被重载
其他不能被重载的 . .* sizeof() :?
怎么做类的定义?常规情况放在栈里面,指针定义放在堆里面
Student str(里面是初始化参数); //放在栈里,函数运行结束自动调用析构函数,这种用.来访问成员变量,.这个运算符时不能被重载的 Student *ptr = new Student(初始化参数); //放在堆里,必须用delete调用析构函数 //下面这种类的对象是匿名的,有了指针以后不用.这个运算符访问,用->这个运算符访问
类的封装特性,实际上就是public protected private三类关键字,
它们在类内均可以被访问,在类外只有public可以被访问,protected只有在继承的时候用到,子类可以被访问
默认是private
结构体默认是public,结构体中也可以定义函数
可以定义public成员函数访问private成员变量
也可以用友元函数访问private成员变量
类的构造函数
必须时public的,private也不会报错但是没有意义
可以重载很多次
构造时访问顺序:静态成员变量 父类构造函数 普通成员变量 本类构造函数
可以在类内定义,在类内定义默认为inline函数
可以在类外定义,类外定义不默认为inline函数,有普通定义形式和类的构造函数初始化列表
其中如果定义const类型必须用类的构造函数初始化列表
有默认构造函数
析构函数
不能重载
有些时候类内有些new定义的指针,在析构函数中必须释放空间
其他的变量时不用的,函数结束时会自动释放空间
放在栈里的类,函数结构自动执行析构函数,放在堆里的类,必须配合delete释放空间
const关键字
const成员变量 const成员函数 const对象
const成员变量
声明和定义的时候都要加上关键字,与static不同,不能被改变的变量
const成员函数
声明和定义都要加上关键字,
它不能改变任何成员变量的值,不只是const类型的,但是可以访问所有成员
const关键字的声明放在形参之后,否则认为时返回的const类型数据
const对象
对象就没有声明了,只有定义时标记上
只能调用类的成员变量和成员函数
static关键字
静态变量:在类声明的时候就分配内存,放在data段,
必须在类外被初始化,
声明的时候加static,定义的时候不带static关键字
初始化可以赋值也可以不赋值,data段自动赋值0,栈自动赋值垃圾值
既能通过类来访问,也可以通过对象来访问,但遵循public private的规则
静态成员函数
只有类能调用,对象不能调用
只能调用静态成员变量和静态成员函数,而普通的成员函数可以访问所偶有成员
声明时添加static,定义的时候不能加
没有this指针
this指针,类中的每个普通成员函数都隐式的含有this指针指向当前对象
this指针的实质是成员函数(变量没有this指针)的一个隐式参数,const类型的(不能被更改)
只能在类内使用,可以访问类内public protected private属性
因为指向当前对象的地址,因此只有在对象创建以后才有this指针,编译时默默添加到参数列表中
static的静态函数没有this指针
友元函数没有this指针
友元函数
在运算符重载中,也用到了友元函数,它和类内定义运算符重载有何区别,形参数量不同
友元函数可以时普通函数,也可以时其他类的成员函数,它可以访问public protected private
在类内声明时加上friend,在定义时不要加friend
友元函数时非成员函数,没有this指针,必须向它传递参数
友元时单向的而不是双向的,友元不能传递
友元类的所有成员函数均是另一个类的友元函数,不建议
类的提前声明
类在正式声明后才能使用,在某些情况下做好提前声明也能使用
但是要创建对象就必须要在正式声明以后
s
创建类的对象的过程?
分配内存
就是在堆区、栈区或者全局数据区留出足够多的字节。它所包含的数据一般是零值或者随机值,没有实际的意义。
初始化过程
首次对内存赋值,其实就是调用构造函数,拷贝构造函数也是在初始化阶段进行的,只不过是用他人的数据来初始化自己的内存
拷贝构造函数:从一个已存在对象中创建一个新的对象
可以和普通构造函数共存, 也可以多次函数重载
Student(string name = “”, int age = 0, float score = 0.0f); //普通构造函数
Student(const Student &stu); //拷贝构造函数(声明)
调用拷贝构造函数可以用等号,也可以用小括号
Student stu1(“小明”, 16, 90.5);
Student stu2 = stu1; //调用拷贝构造函数
Student stu3(stu1); //调用拷贝构造函数
问答
为什么形参列表是引用
如果不是引用,函数传参本事就是拷贝过程,这样也会调用拷贝构造函数,一直这样下去就会永不停止
为什么是const类型
不希望对原有参数做出更改
另外非const类型可以转换为const类型,而反过来不可以
默认拷贝构造函数
系统定义,即为把老对象的值一一赋值给新对象
深拷贝与浅拷贝
引用就是数据的别名,数据地址,值都和原来的变量相同
直接传递参数,相当于拷贝赋值
传递指针参数,相当于对指针拷贝
传递引用参数,正解
可以让形参与实参绑定起来,如果修改了形参的数据,实参的数据也会被修改
按引用传参在使用形式上比指针更加直观。
相当于就是一个别名
不要返回局部数据
可以返回形参
指针可以定义空指针,但引用必须依赖于真实存在的变量
sizeof(指针) = 4不变,而sizeof(引用) = 引用的那个字符占用的空间
指针可以有多级指针,而引用最多只有一级引用
指针可以const 引用不能const
多态与虚函数时绑定的,两个概念没有在其他地方出现过
函数名不用改变,只要改变形参列表就可以
函数的返回类型可以相同也可以不同,但是不能只改变返回类型
C++可以函数重载,C不可以
因为C++在编译的时候对函数名重新定义的,不仅包含函数名,还包含函数形参列表类型
运算符的重载比较麻烦,一般是与类相结合使用,需要定义一个重载运算符的函数
可以在类内定义重载函数
bool opreator+(函数形参) const{...}
也可以在类外用友元函数定义重载函数,类内声明好,类外定义
friend Complex oprator-(函数形参); Complex oprator-(){ }
两者的区别,友元函数没有this指针,因此函数形参列表要有两个,类内定义的函数有this指针默认指向现在的对象,因此形参列表只有一个
不能重载的运算符 . .* :: sizeof() ?:
必须在类内重载的运算符 赋值运算符= 类型转换运算符() 下标运算符[] 成员访问运算符->
必须用友元函数重载的运算符 >> <<
重载不能改变运算符的优先级和结合性
重载不会改变运算符的用法,原有有几个操作数、操作数在左边还是在右边,这些都不会改变
例如,+
号可以对不同类型(int、float 等)的数据进行加法操作;<<
既是位移运算符,又可以配合 cout 向控制台输出数据。C++ 本身已经对这些运算符进行了重载
运算符重载函数除了函数名有特定的格式,其它地方和普通函数并没有区别
必须用友元函数进行运算符重载
friend ostream& operator << (ostream& output, const int& x); ostream& operator << (ostream& output, const int& x){ output << x ; return output; } friend istream& operator << (istream& input, int& x) istream& operator >> (istream& input, int& x){ input >> x; return input; }
模板的定义形式
template <class T1, class T2> int swap(T1 a, T2 b){ ... }
函数模板时怎么调用的
swap(a1, a2); 可以 swap<int, double>(a1, a2); 可以
模板函数是可以重载的
主函数中出现函数名的搜索顺序
查找参数完全匹配的普通函数
查找参数完全匹配的模板函数
查找参数不完全匹配的普通函数,这时普通函数可以做一个隐式的类型转换
报错
模板函数不会做任何隐式的类型转换
s