C++面向对象入门(三十四)纯虚函数和抽象类
纯虚函数: 不能在基类中给出实现, 但是要求所有派生类必须覆盖(重写)或也声明为纯虚函数的虚函数函数
作用: 给所有派生类提供一个操作接口
定义纯虚函数的语法:
virtual 返回值类型 函数名(<参数列表>) = 0
{
<函数体>
}
作用: 给所有派生类提供一个操作接口
定义纯虚函数的语法:
virtual 返回值类型 函数名(<参数列表>) = 0
{
<函数体>
}
调用抽象类的纯虚函数需要使用完全限定函数名(带作用域分辨符)
抽象类: 包含有纯虚函数的类
抽象类的特点:
1 不能被实现
2 不能作为函数返回值类型
3 不能作为参数类型
4 抽象类的引用类型可以作为参数类型和返回类型
5 抽象类的指针类型可以作为参数类型和返回类型
抽象类的特点:
1 不能被实现
2 不能作为函数返回值类型
3 不能作为参数类型
4 抽象类的引用类型可以作为参数类型和返回类型
5 抽象类的指针类型可以作为参数类型和返回类型
抽象类的构造函数和析构函数中不能调用纯虚函数, 析构函数和构造函数调用虚函数采用静态联编, 会报错(纯虚函数没有实现)
抽象类的普通成员函数(非构造函数和析构函数)中可以调用纯虚函数, 采用动态联编, 运行时必然是该抽象类的派生类对象调用派生类中重写的虚函数, 不会报错
抽象类的普通成员函数(非构造函数和析构函数)中可以调用纯虚函数, 采用动态联编, 运行时必然是该抽象类的派生类对象调用派生类中重写的虚函数, 不会报错
代码示例:
#include <iostream> using namespace std; /* 纯虚函数: 不能在基类中给出实现, 但是要求所有派生类必须覆盖(重写)或也声明为纯虚函数的虚函数函数 作用: 给所有派生类提供一个操作接口 定义纯虚函数的语法: virtual 返回值类型 函数名(<参数列表>) = 0 { <函数体> } 调用抽象类的纯虚函数需要使用完全限定函数名(带作用域分辨符) 抽象类: 包含有纯虚函数的类 抽象类的特点: 1 不能被实现 2 不能作为函数返回值类型 3 不能作为参数类型 4 抽象类的引用类型可以作为参数类型和返回类型 5 抽象类的指针类型可以作为参数类型和返回类型 抽象类的构造函数和析构函数中不能调用纯虚函数, 析构函数和构造函数调用虚函数采用静态联编, 会报错(纯虚函数没有实现) 抽象类的普通成员函数(非构造函数和析构函数)中可以调用纯虚函数, 采用动态联编, 运行时必然是该抽象类的派生类对象调用派生类中重写的虚函数, 不会报错 */ class A51 { public: A51(); virtual void func1() = 0; void callFunc1(); }; class B51 : public A51 { public: virtual void func1(); }; class C51 :public A51 { public: }; class D51 : public C51 { public: virtual void func1(); }; //尝试让抽象类类型作函数返回值类型 //A51 func1() //{ // cout << "A51 func1()" << endl; //} //不允许返回抽象类类型"A51"的函数 // 函数A51::func1()是纯虚拟函数 //尝试使用抽象类类型作函数参数 //void func1(A51 a) //{ // cout << "void func1(A51)" << endl; //} //不允许返回抽象类类型"A51"的参数 // 函数A51::func1()是纯虚拟函数 //使用抽象类的引用作函数返回值类型和函数参数 A51 &func1(A51 &a) { cout << "A51 &func1(A51&)" << endl; return a; } //使用指向抽象类类型的指针作函数返回值和函数参数 A51 *func1(A51 *a) { cout << "A51 *func1(A51*)" << endl; return a; } int main() { //尝试使用A51实现对象 //A51 a; //不允许使用抽象类类型"A51"的对象 // A51::func1()是纯虚拟函数 B51 b; b.callFunc1(); //没有实现纯虚函数的派生类 //C51 c; ///不允许使用抽象类类型"C51"的对象 // 纯虚函数"A51::func1()"没有替代项(即未重写基类的纯虚函数, 派生类仍为抽象类) D51 d; d.callFunc1(); //抽象类作引用 A51 &a2 = b; a2.callFunc1(); //指向抽象类的指针 C51 *c2 = &d; c2->callFunc1(); A51 *a3 = func1(c2); a2 = func1(d); system("pause"); } A51::A51() { //func1(); //编译报错 } void A51::callFunc1() { func1(); } void D51::func1() { cout << "D51 func1()" << endl; } void B51::func1() { cout << "B51 func1()" << endl; }
路漫漫其修远兮,吾将上下而求索。