结构体和类
C++结构体中可以有函数。
称为成员函数
#include <iostream> struct point { int x; int y; void output() { std::cout<<x<<std::endl<<y; } }; void main() { point pt; pt.x=0; pt.y=0; pt.output(); }
C++中,结构体使用关键字struct声明的类
差异:结构体默认成员公有public
类:默认成员为private
构造函数
构造函数名字一定和类名相同
#include <iostream> using namespace std; class point { public: int x; int y; point() { x=0; y=0; } point(int a,int b) { x=a; y=b; } void output() { cout<<x<<endl<<y<<endl; } }; void main() { point pt(5,5); pt.output(); point cc; cc.output(); }
析构函数
格式 ~类名()
不允许带参数
一个类只有一个
在程序调用delete删除对象时,析构函数被自动调用
对于一个对象,析构函数是最后一个被调用的成员函数
我们可以为某些成员变量分配堆内存
然后析构函数中释放对象运行期间申请的资源
#include <iostream> using namespace std; class Student { private: char* pName; public: Student() { pName = new char[20]; } ~Student() { delete[] pName; } };
在堆上分配20个字节,结束的时候释放堆上的内存
this指针
this是隐含的指针,指向对象本身,代表对象的地址
pt对象创建的时候,默认this = &pt
类的继承
#pragma once是一个比较常用的C/C++预处理指令,只要在头文件的最开始加入这条预处理指令,就能够保证头文件只被编译一次。
#include"标头.h" using namespace std; class animal { public: void eat() { cout<<"animal eat"<<endl; } void sleep() { cout<<"animal sleep"<<endl; } void breathe() { cout<<"animal breathe"<<endl; } }; class fish:public animal { }; class dog :public animal { }; void main() { animal an; fish fh; an.breathe(); fh.breathe(); dog dd; dd.breathe(); }
public 任意地方访问
protected 只能在类和子类里访问
private 只能在该类自身
类的多重继承:
#include <iostream> using namespace std; class B1 { public: void output(); }; class B2 { public: void output(); }; void B1::output() { cout<<"call the class B1"<<endl; } void B2::output() { cout<<"call the class B2"<<endl; } class A:public B1,public B2 { public: void show(); }; void A::show() { cout<<"call the class A"<<endl; } void main() { A a; //a.output(); //该语句编译时会报错 a.show(); }
虚函数与多态性、纯虚函数
子类父类的关系就是,子类是父类的扩充,就是多一块内存空间
所以子类转父类不用强转
animal *pAn; fish fh; pAn=&fh;
虚函数与多态
#include <iostream> using namespace std; class animal { public: void eat() { cout<<"animal eat"<<endl; } void sleep() { cout<<"animal sleep"<<endl; } virtual void breathe() { cout<<"animal breathe"<<endl; } }; class fish:public animal { public: void breathe() { cout<<"fish bubble"<<endl; } }; void fn(animal *pAn) { pAn->breathe(); } void main() { animal *pAn; fish fh; pAn=&fh; fn(pAn); }//结果是fish bubble
虚函数就像接口等着实现
多态:在基类的函数前加上virtual关键字,在派生类中重写该函数,运行时会根据对象的实际类型来调用相应函数
c++在编译的时候,如果发现virtual,会采用迟绑定
在运行时,看对象的类型来确定哪个函数被调用-----------多态性
纯虚函数
virtual void breathe() = 0;
纯虚函数是一种特殊的虚函数,它的一般格式如下(C++格式):
class <类名> { virtual <类型><函数名>(<参数表>)=0; … };
在许多情况下,在基类中不能对虚函数给出有意义的实现,而把它声明为纯虚函数,它的实现留给该基类的派生类去做。这就是纯虚函数的作用。
覆盖和隐藏
隐藏:当父类函数与派生类函数同名,并且父类函数无 virtual关键字修饰,无论父类与派生类参数个数与类型是否相同,此时派生类函数隐藏父类所有同名函数
覆写:当父类函数与派生类函数同名,并且参数相同,返回值相同,并且父类函数有 virtual关键字修饰,此时派生类函数覆写父类函数
引用
引用会使用同一块地址
常用于传参--------------节省空间,也更直观
int a=5; int &b=a; void f(int& a, int &b) { }
C++类的设计习惯及头文件包含问题
函数在头文件加入virtual后,在cpp文件就不用加virtual了
重复定义,
#ifndef XXX//名字随便取,一般有实际意义 比如ANIMAL_H #define XXX class animal { public: animal(); ~animal(); void eat(); void sleep(); virtual void breathe(); }; class doge { }; #endif // !XXX