C++

C++ 知识量:19 - 82 - 316

15.3 虚函数><

什么是虚函数- 15.3.1 -

在C++中,虚函数是一种特殊类型的成员函数,它在基类中被声明为虚函数后,可以在派生类中被重写。这样当通过基类指针或引用调用这个函数时,程序会动态地确定应该调用哪个类的成员函数。

以下是一个简单的使用虚函数的例子:

#include <iostream>  
  
// 基类  
class Base {  
public:  
    // 声明虚函数  
    virtual void print() {  
        std::cout << "这是基类的虚函数。" << std::endl;  
    }  
};  
  
// 派生类  
class Derived : public Base {  
public:  
    // 重写基类的虚函数  
    void print() override {  
        std::cout << "这是派生类的虚函数。" << std::endl;  
    }  
};  
  
int main() {  
    Base* base_ptr = new Derived(); // 基类指针指向派生类  
    base_ptr->print(); // 调用的是派生类的print()函数  
    delete base_ptr; // 不要忘记删除指针!  
    return 0;  
}

在这个例子中,基类Base有一个虚函数print,而派生类Derived重写了这个虚函数。在主函数中,创建了一个指向Derived类的Base类指针,然后通过这个指针调用了print函数。由于print函数在基类中被声明为虚函数,所以调用的是Derived类的print函数,而不是Base类的print函数。这就是多态性的一个体现。

C++的多态性- 15.3.2 -

C++的多态性是一种面向对象编程的核心概念,它允许一个接口(或基类)引用不同类型的对象,而这些不同类型的对象可以使用相同的接口方法进行操作。多态性是C++的一个重要特性,它提供了更好的代码重用和灵活性。

C++中的多态性可以通过虚函数来实现。虚函数是一种在基类中声明的函数,它可以被子类重写,从而实现多态性。在基类中声明虚函数时,需要在函数声明后面添加virtual关键字,以表示该函数是一个虚函数。在派生类中重写基类的虚函数时,需要使用override关键字来表明该函数是重写基类的虚函数。

下面是一个简单的示例代码,演示了C++的多态性:

#include <iostream>  
  
// 基类  
class Shape {  
public:  
    virtual void draw() {  
        std::cout << "这是基类的 draw() 函数。" << std::endl;  
    }  
};  
  
// 派生类 1  
class Circle : public Shape {  
public:  
    void draw() override {  
        std::cout << "这是派生类 Circle 的 draw() 函数。" << std::endl;  
    }  
};  
  
// 派生类 2  
class Rectangle : public Shape {  
public:  
    void draw() override {  
        std::cout << "这是派生类 Rectangle 的 draw() 函数。" << std::endl;  
    }  
};  
  
int main() {  
    Shape* shape_ptr = new Circle(); // 基类指针指向派生类 Circle  
    shape_ptr->draw(); // 调用的是派生类 Circle 的 draw() 函数  
    delete shape_ptr; // 不要忘记删除指针!  
  
    shape_ptr = new Rectangle(); // 基类指针指向派生类 Rectangle  
    shape_ptr->draw(); // 调用的是派生类 Rectangle 的 draw() 函数  
    delete shape_ptr; // 不要忘记删除指针!  
  
    return 0;  
}

在这个例子中,基类Shape有一个虚函数draw,而派生类Circle和Rectangle重写了这个虚函数。在主函数中,创建了一个指向Circle类的Shape类指针,然后通过这个指针调用了draw函数。由于draw函数在基类中被声明为虚函数,所以调用的是Circle类的draw函数,而不是Shape类的draw函数。接着,创建了一个指向Rectangle类的Shape类指针,并调用了draw函数。这次调用的是Rectangle类的draw函数。这就是多态性的体现,同一个接口可以操作不同类型的对象。

final和override说明符- 15.3.3 -

在C++中,final和override是两种说明符,它们主要用于面向对象编程中的多态性。

final:这个关键字用于防止基类的派生类被进一步派生。使用final关键字的类不能被继承。创建一个类并希望它不能被扩展时,可以使用final。

例如:

class Base {  
public:  
   virtual void func() final; // 'Base'类中的函数被标记为 'final'  
};

override:这个关键字用于在派生类中表明一个成员函数重写了基类中的虚函数。如果尝试在派生类中定义一个与基类中虚函数名称、参数列表相同的函数,但没有使用override关键字,这可能是一个错误,因为C++不会强制要求在这种情况下重写虚函数。但是,如果使用了override关键字,如果基类中没有相应的虚函数,编译器就会报错。

例如:

class Base {  
public:  
   virtual void func(); // 基类的虚函数  
};  
  
class Derived : public Base {  
public:  
   void func() override; // 'Derived'类中的函数重写了基类中的虚函数  
};

这两个关键字一起使用可以增加代码的清晰度,并提供更好的编译时错误检查。

抽象基类- 15.3.4 -

C++的抽象基类是一个特殊的类,它不能被实例化,只能被用作其他类的基类。抽象基类中可以包含纯虚函数,这些函数在派生类中必须被重写。纯虚函数是没有实现的函数,它们的声明以=0结尾。例如:

class AbstractClass {  
public:  
   virtual void pureVirtualFunction() = 0; // 纯虚函数  
};

抽象基类中的成员函数通常也是保护的,即它们不能被直接访问,只能在派生类中被访问。

抽象基类的主要目的是定义一个接口,使得其他类可以继承这个接口并实现其中的纯虚函数。这样,可以保证派生类具有相同的接口,从而实现多态性。例如:

class DerivedClass : public AbstractClass {  
public:  
   void pureVirtualFunction() override { // 重写抽象基类中的纯虚函数  
      // 实现代码  
   }  
};

在这个例子中,DerivedClass继承了AbstractClass并实现了其中的纯虚函数pureVirtualFunction()。这样,就可以使用AbstractClass类型的指针或引用指向DerivedClass的对象,并调用pureVirtualFunction()函数。例如:

AbstractClass* ptr = new DerivedClass(); // 抽象基类指针指向派生类对象  
ptr->pureVirtualFunction(); // 调用的是派生类中的实现,实现多态性  
delete ptr; // 不要忘记删除指针!