#include <iostream.h> class POINT { public: int x; int y; POINT()//构造函数 { x=0; y=0; } void output() { cout<<x<<endl<<y<<endl; } }; void main() { POINT pt;//在定义类的变量时自动调用构造函数 pt.output(); }
1.类里面默认的成员为私有,结构体里面的成员变量为公有
2.构造函数,在main函数定义类变量时,自动调用构造函数
3.析构函数,不允许带参数,并且一个类中只能存在一个析构函数
4.函数的重载,我们希望在构造pt这个对象的同时,传递x坐标和y坐标的值.可以再定义一个构造函数.两个构造函数
#include <iostream.h> 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(); }
C++编译器将根据参数的类型和参数的个数来确定执行哪一个构造函数,如上执行POINT(int a,int b)
重载的条件:函数的参数类型,参数个数不同,才能构成重载 只有返回类型不同是不能构成重载的
this 指针 它是一个隐含的指针,在调用对象时,成员函数除了接受2个实参外,还接受了pt对象的指针
#include <iostream.h> 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 input(int x,int y) { this->x=x; this->y=y; } }; void main() { POINT pt(5,5);//在定义类的变量时自动调用构造函数 pt.input(10,10); pt.output(); }
类的继承
#include <iostream.h> class animal { public: void eat() { cout<<"animal eat"<<endl; } void sleep() { cout<<"animal sleep"<<endl; } void breath() { cout<<"animal breath"<<endl; } }; class fish:public animal { }; void main() { animal an; fish fh; an.eat(); fh.eat(); }
在c++中提供了一种重要的机制,就是继承。我们可以基于animal这个类来创建fish类,animal称为基类.fish称为派生类.
class fish:public animal//fish继承animal { };
为基类和派生类加入构造函数和析构函数
#include <iostream.h> class animal { public: animal() { cout<<"animal construct"<<endl; } ~animal() { cout<<"animal destruct"<<endl; } void eat() { cout<<"animal eat"<<endl; } void sleep() { cout<<"animal sleep"<<endl; } void breath() { cout<<"animal breath"<<endl; } }; class fish:public animal { public: fish() { cout<<"fish construct"<<endl; } ~fish() { cout<<"fish destruct"<<endl; } }; void main() { fish fh; }
当构造fish类的对象fh时,animal类的构造函数也要被调用,而且在fish类的构造函数调用之前被调用.当然,这也很好理解,没有父亲就没有孩子,在析构时,先析构派生类再析构基类.
#include <iostream.h> class animal { public: animal(int height,int weight)//基类构造函数带参数 { cout<<"animal construct"<<endl; } ~animal()//析构函数都不带参数 { cout<<"animal destruct"<<endl; } void eat() { cout<<"animal eat"<<endl; } void sleep() { cout<<"animal sleep"<<endl; } void breath() { cout<<"animal breath"<<endl; } }; class fish:public animal { public: fish():animal(400,300) { cout<<"fish construct"<<endl; } ~fish() { cout<<"fish destruct"<<endl; } }; void main() { fish fh; }
public定义的成员可以在任何地方被访问
protected定义的成员只能在该类及其子类中访问
private定义的成员只能在该类自身中访问
对于继承,也可以有以上三种访问权限去继承基类中的成员
注意:基类中的private成员不能被派生类访问,因此,private成员不能被派生类所继承.
多重继承:一个类可以从多个基类中派生。在派生类由多个基类派生的多重继承模式中。多重继承的语法与单一继承很类似,只需要在声明继承的多个类之间加入逗号来分割。
虚函数与多态性,纯虚函数:
#include <iostream.h> class animal { public: void eat() { cout<<"animal eat"<<endl; } void sleep() { cout<<"animal sleep"<<endl; } void breath() { cout<<"animal breath"<<endl; } }; class fish:public animal { public: void breath()//在fish类中重新定义了breath()方法,吐泡泡 { cout<<"fish bubble"<<endl; } }; void fn(animal *pAn)//全局函数fn() { pAn->breath(); } void main() { animal *pAn; fish fh;//定义了一个fish类的对象 pAn=&fh;//将它的地址传给animal类的指针变量 fn(pAn);//调用fn() }
main函数中,定义了一个全局函数fn(),指向animal类的指针作为fn()函数的参数。
我们将fish类的对象fh的地址直接赋值给了animal类的指针变量
这是因为fish对象也是一个animal对象,将fish类型转换为animal类型不用强制类型转换。
virtual void breath() { cout<<"animal breath"<<endl; }
用virtual关键字申明的函数叫做虚函数。C++会采用迟绑定计数。也就是编译时并不确定具体调用的函数,而是在运行时,依据对象的类型来确定调用的是哪一个函数,这种能力就叫做c++的多态性
即:在基类的函数前面加上virtual关键字,在派生类中重写该函数,运行时将会根据对象的实际类型来调用相应的函数。如果对象类型是派生类,就调用派生类的函数;如果对象类型是基类,就调用基类的函数。
纯虚函数:
纯虚函数可以让类先具有一个操作名称,而没有具体的操作内容,让派生类再继承时在去具体的给出定义。凡是含有纯虚函数的类叫做抽象类,这种类不能声明对象,只是作为基类为派生类服务。在派生类中必须完全实现基类的纯虚函数,否则,派生类也变成了抽象类,不能实例化对象。
函数的覆盖:
*基类函数必须是虚函数。
*发生覆盖的两个函数分别位于派生类和基类中。
*函数名称与参数列表必须完全相同。
函数的隐藏:
所谓隐藏,是指派生类中具有与基类同名的函数,从而在派生类中隐藏了基类的同名函数。
区分覆盖和隐藏:
函数的覆盖是发生在派生类与基类之间,两个函数必须完全相同,并且都是虚函数。那么不属于这种情况的,就是隐藏了.
C++类的设计习惯及头文件重复包含问题的解决
在设计一个类的时候,通常将类的定义及类成员函数的声明放到头文件(即.h文件)中,将类中成员函数的实现放到源文件中
(.cpp)中
对于animal类需要把animal.h和animal.cpp两个文件,其余类相同
对于main()函数,我们把它单独放到EX10.cpp文件中.