C++面向对象入门(三十四)纯虚函数和抽象类

纯虚函数: 不能在基类中给出实现, 但是要求所有派生类必须覆盖(重写)或也声明为纯虚函数的虚函数函数
作用: 给所有派生类提供一个操作接口
定义纯虚函数的语法:
virtual 返回值类型 函数名(<参数列表>) = 0
{
 <函数体>
}
调用抽象类的纯虚函数需要使用完全限定函数名(带作用域分辨符)
抽象类: 包含有纯虚函数的类
抽象类的特点:
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;
}

 

posted @ 2020-09-01 17:36  DNoSay  阅读(292)  评论(0编辑  收藏  举报