C++基础教程(总结)(三)
}
Date::Date(int y, int m, int d)
{
? ? year ?= y;
? ? month = m;
? ? day ? = d;
}
?
int main()
{
? ? Time t(5,5,5);
? ? Time t1(t); //对象的复制
? ? Date d(2000,10,30), d1;
? ? d1 = d; ? ? //对象的赋值
? ? t.display(d);
? ? t1.display(d1);
? ??
? ? return 0;
}
复制代码
?
?
14、运算符重载
?
实质上是函数重载
形式:函数类型 operator运算符名称(形参表列){};
重载不能改变运算符运算对象的个数、优先级别、结合性,不能有默认的参数,参数至少有一个类对象(其引用)
C++约定:若在前置自增(自减)运算符重载函数中增加一个int型形参,就是后置(自减)运算符函数
只能将重载“>>”和“<<”的函数作为友元函数或普通的函数,而不能将他们定义为成员函数
15、继承和派生
?
继承:一个新类从已有的类那里获得其已有特性
派生:从已有的类(基类)产生一个新的子类(派生类)
继承与组合:在一个类中以另一个类的对象作为数据成员
继承分单继承和多重继承,派生分一级派生和多级派生
继承方式:公用、保护、私有
访问属性:公用、保护、私有、不可访问
派生类的成员:基类的全部成员(不包括构造和析构函数)+自己增加的成员
私有成员只能被本类的成员函数访问,保护成员可被派生类的成员函数引用
类的成员在不同的作用域中有不同的访问属性
?
派生类的构造与析构函数:
派生类构造函数名(总参数表列):基类构造函数名(参数表列),…,子对象名(参数表列),… ?{ 派生类新增数据成员的初始化语句 }
派生类构造函数的执行顺序:基类、子对象、派生类
多重继承中的初始化是按基类表中的说明顺序进行的
析构函数与构造函数相反
若基类未定义构造函数或定义了未带参数的构造函数,则在派生类中可不写基类构造函数;在调用派生类构造函数时系统会自动首先调用基类默认的构造函数
多重继承引起的二义性问题:
?
基类与派生类的转换:
?
继承与派生源代码:
复制代码
#include
#include
using namespace std;
?
class Person
{
public:
? ? Person(string nam,int a,char s):name(nam),age(a),sex(s)
? ? {
? ? }
? ? void show()
? ? {
? ? ? ? cout<<"name:" <<'\t'<
? ? ? ? ? ? <<"age:" ?<<'\t'<
? ? ? ? ? ? <<"sex:" ?<<'\t'<
? ? {
? ? }
protected:
? ? string name;
? ? int age;
? ? char sex;
};
?
class Teacher:virtual public Person//声明Person为公用继承的虚基类
{
public:
? ? //构造函数
? ? Teacher(string nam,int a,char s,string t):Person(nam, a,s),title(t)
? ? }
? ? void display()
? ? {
? ? ? ? show();
? ? ? ? cout<<"title:"<<'\t'<
? ? }
protected:
? ? string title;
};
class Student:virtual public Person//声明Person为公用继承的虚基类
{
public:
? ? //构造函数
? ? Student(string nam, int a,char s,float sco):Person(nam,a,s),score(sco)
? ? {
? ? }
? ? void display()
? ? {
? ? ? ? show();
? ? ? ? cout<<"score:"<<'\t'<
? ? }
protected:
? ? float score;
};
?
class Graduate:public Teacher,public Student//声明多重继承的派生类Graduate
{
public:
? ? //不仅要对直接基类初始化,还要对虚基类初始化
? ? Graduate(string nam,int a,char s,string t,float sco,float w):
? ? ? Person(nam,a,s),Teacher(nam,a,s,t),Student(nam,a,s,sco),wage(w)
? ? ?{
? ? ?}
? ? ?void present()
? ? ?{
? ? ? ? cout<<"name:" <<'\t'<
? ? ? ? ? ? <<"age:" ?<<'\t'<
? ? ? ? ? ? <<"sex:" ?<<'\t'<
? ? ? ? ? ? <<"title:"<<'\t'<
? ? ? ? ? ? <<"score:"<<'\t'<
? ? ? ? ? ? <<"wage:" <<'\t'<
? ? ?}
private:
? ? float wage;
};
?
?
int main()
{
? ? Graduate grad1("WangLi",24,'f',"assistant",99.5,1325.5);
? ? grad1.present();
? ??
? ? return 0;
}
复制代码
16、多态性和虚函数
?
多态性:用一个函数名调用具有不同内容(功能)的函数;不同对象对同一消息有不同的响应方式(一个接口,多种方法)
从系统实现的角度,多态性分为:静态多态性(编译时的多态性)和动态多态性(运行时的多态性,通过虚函数实现)
关联:调用具体的对象的过程(把一个函数名与一个对象捆绑在一起)
静态(早期)关联:通过对象名调用虚函数,在编译时即可确定其调用的函数属于哪个类
动态(滞后)关联:通过基类指针调用虚函数,在运行阶段把虚函数和类对象捆绑在一起
虚函数:
?
类外定义虚函数时不必加virtual
派生类中定义的同名函数:函数名、类型、参数个数、参数类型须与虚函数相同;当一个成员函数被声明为虚函数后,其派生类的同名函数都自动成为虚函数
先用基类对象指针指向同一类族中某一对象,即可调用该对象中的同名函数
函数重载处理的是同一层次上的同名函数问题,而虚函数处理的是不同派生层次上的同名函数问题(函数覆盖)
当一个类有虚函数时,编译系统会为该类构造一个虚函数表(一个指针数组),存放每个虚函数的入口地址
构造函数不能声明为虚函数;若基类的析构函数声明为虚函数,则其所有派生类的析构函数均为虚函数
纯虚函数与抽象类:
纯虚函数:virtual 函数类型 函数名(参数表列)=0;//声明语句
?
无函数体;“=0”并不表示返回值为0,只是形式;不具备函数的功能,不能被调用
若在派生类中未对该函数定义,则在派生类中仍为纯虚函数
抽象类:不用来定义对象,只作为一种基本类型用作继承的类
?
可定义指向抽象类对象的指针变量,通过指针调用具体派生类的虚函数