1、类
1、定义
类包含了数据表示法和处理数据的方法,都被称为成员,函数在类中也被称为成员。
一般情况类的数据成员都定义为私有成员,而函数成员为共有成员。
类成员函数可以访问任何的数据成员。不管是私有的还是被保护的。
2、友元函数
(友元函数/类破坏了类的封装性,一般不太使用。)
友元函数不是类的成员函数,但是可以访问类中的成员,包括私有成员。需要在类中声明一下友元函数:
class A{
public:
friend int A(int a,int b) //A为友元函数,可以访问类中的任意成员。还可以定义在private下边。
}
友元类具有相同的用法。
注意:友元函数和友元类无法被继承。
2、继承
一个类继承另一个类,原来就存在的类叫做 基类,后来继承的叫做派生类。
class Animal{
//sleep函数
//eat函数
};
class Dog: public Animal,public B{ //继承了两个基类:Animal,B,用逗号分开。
//bark函数
};
默认情况下是private继承。
一个派生类可以继承多个基类。派生类可以访问基类的非私有成员
3、重载函数和重载运算符
重载函数
在同一个定义域内多次定义同一个函数或运算符。
同一个函数或运算符名称一样,但是参数类型、参数个数、或者顺序不同。不能通过返回类型的不同来重载函数。
在编译时,编译器会将重载函数与调用的函数进行参数类型的对比,找到最合适的函数 ——重载决策。
重载运算符
对已经存在的运算符进行重新定义。
重载的运算符是特殊的函数: 类型 operator+(参数) ,对+号进行重载。
重载、覆盖、重定义
重载:发生在函数、运算符之间,重载函数的名称相同,但是参数个数、类型或者顺序不能相同,不能返回类型不同而重载函数。
覆盖:发生在类中,子类对基类的成员函数进行重新定义,函数名称、参数、返回类型要相同。
重定义:子类对父类的非虚函数进行重定义,名称一样,参数可以不同。
4、多态
多态发生在类中,尤其在继承中。根据调用函数的对象的类型来执行不同的函数。
子类可以定义一个与基类相同的成员函数,实现方式不同,甚至参数都是可以相同的。
虚函数
虚函数是定义在基类中,在子类中要重新定义的函数:
class Shape{
protected:
int width,height;
public:
Shape( int a=0, int b=0)
{
width = a;
height = b;
}
virtual int area() //虚函数:在函数前面使用关键字 virtual 声明,告诉编译器不要静态链接到该函数
{
cout << "Parent class area :" <<endl;
return 0;
}
};
纯虚函数
需要在基类中给出虚函数,以便在子类中重新定义函数,但是在基类中又无法给出具体的函数实现,这时可以使用纯虚函数:
class Shape {
protected:
int width, height;
public:
Shape( int a=0, int b=0)
{
width = a;
height = b;
}
// pure virtual function
virtual int area() = 0; //纯虚函数,没有给出具体实现
};
PS(很重要)
- 形成多态的条件:
1、类间必须存在继承关系
2、继承关系必须有同名虚函数
3、存在基类类型的指针或引用,通过该指针或引用调用虚函数。
#include <iostream>
using namespace std;
class Shape {
protected:
int width, height;
public:
Shape( int a=0, int b=0)
{
width = a;
height = b;
}
int area()
{
cout << "Parent class area :" <<endl;
return 0;
}
};
class Rectangle: public Shape{
public:
Rectangle( int a=0, int b=0):Shape(a, b) { }
int area ()
{
cout << "Rectangle class area :" <<endl;
return (width * height);
}
};
class Triangle: public Shape{
public:
Triangle( int a=0, int b=0):Shape(a, b) { }
int area ()
{
cout << "Triangle class area :" <<endl;
return (width * height / 2);
}
};
// 程序的主函数
int main( )
{
Shape *shape; //第三个条件:通过指针调用虚函数。
Rectangle rec(10,7);
Triangle tri(10,5);
// 存储矩形的地址
shape = &rec;
// 调用矩形的求面积函数 area
shape->area();
// 存储三角形的地址
shape = &tri;
// 调用三角形的求面积函数 area
shape->area();
return 0;
}
- 纯虚函数、虚函数的声明:
virtual void funtion1()=0; //纯虚函数的声明
virtual ReturnType FunctionName(Parameter);//虚函数的声明
- 友元函数不是成员函数,只有成员函数才能是虚函数,所以友元函数不能是虚拟的,但是可以通过友元函数调用虚函数来解决友元函数的虚拟问题。
析构函数应该是虚函数。 - 父类中的虚函数在子类中依然是虚函数。如果避免某个成员函数被重写,可以使用final关键字:
#include<iostream>
using namespace std;
class Base // final :如果不希望类被继承,也可以使用final关键字
{
public:
virtual void func()
{
cout<<"This is Base"<<endl;
}
};
class _Base:public Base
{
public:
void func() final//正确,func在Base中是虚函数 ,但是再有子类就无法再重写。
{
cout<<"This is _Base"<<endl;
}
};
5、抽象类(接口)
一个类中包含纯虚函数,则该类为抽象类。抽象类不能被实例化,只有在纯虚函数被具体实现后才能进行实例化。(跟多态有点像)