Introduction to C++ virtual functions, pure virtual functions, abstract classes and polymorphism

Introduction to C++ virtual functions, pure virtual functions, abstract classes and polymorphism

C++ virtual function, pure virtual function

Virtual function (Virtual Function):

A virtual function is a member function declared as virtual in a base class. By using a virtual function, the function can be redefined in the derived class to realize dynamic binding at runtime. When a virtual function is called through a base class pointer or reference, it actually determines which class version to call based on the type of object pointed to by the pointer or reference.

The syntax for declaring a function as virtual in a base class is as follows:

virtual return type function name (parameter list) {

    // function body

}

The virtual function declaration contains virtual

When we use virtual functions in C++, we usually create a base class (parent class) and one or more derived classes (subclasses). Here is a complete example showing how to use virtual functions:

#include <iostream>
using namespace std; 

// 基类 Animal
class Animal {
public:
    virtual void makeSound() {
        cout << "动物发出声音" << endl;
    }
};

// 派生类 Dog
class Dog : public Animal {
public:
    void makeSound() override {
        cout << "汪汪!" << endl;
    }
};

// 派生类 Cat
class Cat : public Animal {
public:
    void makeSound() override {
        cout << "喵喵!" << endl;
    }
};

int main() {
    Animal* animalPtr;

    // 创建一个 Dog 对象,并将其地址赋值给基类指针
    animalPtr = new Dog();
    animalPtr->makeSound(); // 调用 Dog 类中重写的 makeSound 函数

    // 创建一个 Cat 对象,并将其地址赋值给基类指针
    animalPtr = new Cat();
    animalPtr->makeSound(); // 调用 Cat 类中重写的 makeSound 函数

    delete animalPtr; // 释放内存

    return 0;
}

In the example, a base class Animal and two derived classes Dog and Cat are defined. The makeSound function in the Animal class is declared virtual and overridden in derived classes.

In the main function, first create a base class pointer animalPtr, and then point it to Dog and Cat objects respectively. When the makeSound function is called through the base class pointer, it will actually call the rewritten function in the corresponding derived class according to the type of the object.

Pure Virtual Function:

A pure virtual function is a member function declared as a pure virtual function in the base class, which has only a function declaration but no function definition. Pure virtual functions have no default implementation in the base class, and derived classes must provide their own implementation. A class that contains pure virtual functions in a base class is called an abstract class, and an abstract class cannot be instantiated and can only be inherited as a base class.

The syntax for declaring a function as a pure virtual function in a base class is as follows:

virtual return type function name (parameter list) = 0;

The pure virtual function declaration contains virtual and = 0

When we want to create an abstract base class (Abstract Base Class) in C++, we can use pure virtual functions. Pure virtual functions are virtual functions that are not actually defined, they are only used to provide an interface and must be implemented in derived classes. Here is a complete example showing how to use pure virtual functions:

#include <iostream>
using namespace std; 

// 抽象基类 Animal
class Animal {
public:
    virtual void makeSound() = 0; // 纯虚函数,没有实际定义
};

// 派生类 Dog
class Dog : public Animal {
public:
    void makeSound() override {
        cout << "汪汪!" << endl;
    }
};

// 派生类 Cat
class Cat : public Animal {
public:
    void makeSound() override {
        cout << "喵喵!" << endl;
    }
};

int main() {
    Animal* animalPtr;

    // 创建一个 Dog 对象,并将其地址赋值给基类指针
    animalPtr = new Dog();
    animalPtr->makeSound(); // 调用 Dog 类中实现的 makeSound 函数

    // 创建一个 Cat 对象,并将其地址赋值给基类指针
    animalPtr = new Cat();
    animalPtr->makeSound(); // 调用 Cat 类中实现的 makeSound 函数

    delete animalPtr; // 释放内存

    return 0;
}

In the example, an abstract base class Animal is defined, which contains a pure virtual function makeSound. Derived classes Dog and Cat must implement this pure virtual function, otherwise they will become abstract classes themselves.

In the main function, first create a base class pointer animalPtr, and then point it to Dog and Cat objects respectively. When the makeSound function is called through the base class pointer, it will actually call the function implemented in the corresponding derived class according to the type of the object.

Virtual functions and pure virtual functions in C++ are important concepts in object-oriented programming. They are used to implement polymorphism and base-derived class relationships. Here is an example using both virtual and pure virtual functions:

#include <iostream>
using namespace std;

// 基类 Animal
class Animal {
public:
    // 虚函数,可以被派生类重新定义
    virtual void makeSound() {
        cout << "Animal makes sound" << endl;
    }

    // 纯虚函数,必须在派生类中实现
    virtual void showInfo() = 0;
};

// 派生类 Dog
class Dog : public Animal {
public:
    void makeSound() override {
        cout << "Dog barks" << endl;
    }

    void showInfo() override {
        cout << "I am a dog" << endl;
    }
};

// 派生类 Cat
class Cat : public Animal {
public:
    void makeSound() override {
        cout << "Cat meows" << endl;
    }

    void showInfo() override {
        cout << "I am a cat" << endl;
    }
};

int main() {
    Animal* animalPtr;

    Dog dog;
    Cat cat;

    animalPtr = &dog;
    animalPtr->makeSound();  // 输出:Dog barks
    animalPtr->showInfo();   // 输出:I am a dog

    animalPtr = &cat;
    animalPtr->makeSound();  // 输出:Cat meows
    animalPtr->showInfo();   // 输出:I am a cat

    return 0;
}

In the above example, we defined a base class Animal, which contains a virtual function makeSound () and a pure virtual function showInfo (). The derived classes Dog and Cat respectively inherit from the base class Animal and rewrite these two functions.

In the main function, we use the base class pointer animalPtr to point to the Dog object and the Cat object respectively, and realize polymorphism by calling virtual functions. No matter which object animalPtr points to, it can call the corresponding function according to the actual type of the object.

Run the above example, the output is as follows:

Dog barks
I am a dog
Cat meows
I am a cat

By using virtual functions and pure virtual functions, we can call the corresponding function according to the actual type of the object, realizing the effect of polymorphism.

Abstract Classes

In C++, a class with pure virtual functions is called an abstract class. An abstract class is a special class that cannot directly instantiate objects. Abstract classes are used to define interfaces and shared functionality, and require derived classes to implement specific methods.

In order to define a class as an abstract class, you can declare one or more pure virtual functions (Pure Virtual Function) in the class. A pure virtual function is a virtual function declared in a base class but not implemented, specified by using "= 0".

An abstract class acts as a specification or interface, providing a set of public methods (including pure virtual functions) that derived classes must implement in order to be instantiated. Abstract classes can derive other concrete classes, and these derived classes must implement pure virtual functions in the base class.

Here is a sample code:

#include <iostream>
using namespace std;

// Abstract class
class AbstractClass {
public:
    // Pure virtual function
    virtual void pureVirtualFunction() = 0;

    // Normal member function:普通成员函数
    void normalFunction() {
        cout << "这是一个普通函数。" << endl;
    }
};

// Concrete class inheriting from AbstractClass:继承自抽象类的具体类
class ConcreteClass : public AbstractClass {
public:
    void pureVirtualFunction() override {
        cout << "这是纯虚函数的实现。" << endl;
    }
};

int main() {
    // Creating an object of ConcreteClass
    ConcreteClass concreteObj;

    // Calling member functions
    concreteObj.pureVirtualFunction();
    concreteObj.normalFunction();

    return 0;
}

In this example, we define an abstract class named AbstractClass, which contains a pure virtual function pureVirtualFunction() and an ordinary member function normalFunction(). A pure virtual function has no concrete implementation, indicating that it must be overridden in derived classes.

ConcreteClass is a concrete class inherited from AbstractClass, which provides the implementation of pure virtual functions.

In the main() function, we created a ConcreteClass object and called pure virtual functions and ordinary functions.

The output of the program running is:

This is the implementation of pure virtual functions.
This is an ordinary function.

C++ polymorphism (polymorphism )

C++ polymorphism simply means that when class objects with different inheritance relationships call the same function, different behaviors are produced.

Polymorphism is an important concept in object-oriented programming.

Polymorphism in C++ refers to calling member functions (methods) of derived classes through pointers or references of base classes, and executing different member functions (methods) according to the actual type of the object.

There are two forms of polymorphism in C++: static polymorphism (static polymorphism) and dynamic polymorphism (dynamic polymorphism).

In C++, both override and overload can help programmers achieve polymorphism.

Overriding means redefining a function in a derived class with the same name and parameter list as in the base class. By overriding, derived classes can redefine existing functions in the base class and use new implementations. That way, when the function is called through a pointer or reference to the base class, the version in the derived class is actually executed.

Overloading refers to defining multiple functions with the same name but different parameter lists in the same scope. Overloading allows different behaviors to be expressed using the same function name.

Override and overload in C++, see https://blog.csdn.net/cnds123/article/details/131653045

Key concepts of polymorphism include:

Virtual function: A function declared in a base class that can be overridden by a derived class. Use the virtual keyword for identification.

Dynamic polymorphism (dynamic polymorphism) and static polymorphism (static polymorphism):

Dynamic polymorphism is the determination of function calls at runtime, also known as runtime polymorphism or dynamic binding (dynamic binding). It does this by using virtual functions and dynamic binding. When a virtual function is called through a base class pointer or reference, it actually chooses which function to call at runtime based on the type of the object. In this way, the specific implementation of the function can only be determined at runtime.

Static polymorphism is the determination of function calls at compile time, also known as compile-time polymorphism. It does this by using function overloading and function templates. The compiler selects the appropriate function to call based on the parameter types passed in when the function is called. In this way, the specific implementation of the function can be determined at compile time.

Upcasting: The process of assigning a derived class object to a base class pointer or reference. Through upcasting, derived class objects can be treated as base class objects.

Overriding: Redefining and implementing functions declared as virtual functions in the base class in the derived class. Overriding supersedes the function implementation in the base class.

The main polymorphic implementation methods in C++:

1. Realize polymorphism through virtual function (virtual function) and dynamic binding (dynamic binding). Declare the function that needs to be rewritten as a virtual function in the base class, rewrite it in the derived class, and use the override keyword to ensure correct inheritance. When a derived class object is pointed to through a base class pointer or reference, the function in the derived class is called. This approach is called dynamic polymorphism, because the function to call is determined at runtime based on the type of the actual object.

Example of polymorphism through virtual functions and dynamic binding:

#include <iostream>
using namespace std;

class Animal {
public:
    virtual void makeSound() {
        cout << "Animal is making a sound." << endl;
    }
};

class Dog : public Animal {
public:
    void makeSound() override {
        cout << "Dog is barking." << endl;
    }
};

int main() {
    Animal* animal = new Animal();
    Dog* dog = new Dog();

    animal->makeSound(); // 输出:"Animal is making a sound."
    dog->makeSound();    // 输出:"Dog is barking."

    Animal* ptr = dog;
    ptr->makeSound();    // 输出:"Dog is barking."

    delete dog;
    delete animal;
    return 0;
}

2. Use pure virtual function (pure virtual function) and abstract base class (abstract base class) to realize pure virtual function. A pure virtual function has no actual definition in the base class, and derived classes must override the function in order to instantiate it. Abstract base classes cannot be instantiated and can only be used as interfaces. for dynamic polymorphism.

Example of polymorphism using pure virtual functions and abstract base classes:

#include <iostream>
using namespace std;

class Shape {
public:
    virtual double calculateArea() const = 0; // 纯虚函数
};

class Circle : public Shape {
private:
    double radius;
public:
    Circle(double r) : radius(r) {}
    double calculateArea() const override {
        return 3.14 * radius * radius;
    }
};

int main() {
    Circle circle(5);
    Shape* shape = &circle;

    cout << "Area of the circle: " << shape->calculateArea() << endl; // 输出:Area of the circle: 78.5

    return 0;
}

3. Through function overloading (function overloading) to achieve static polymorphism. Function overloading allows multiple functions with the same name to be defined in the same scope, but with different parameter types, number or order of parameters. The compiler chooses the appropriate function to call based on the type of the actual parameter. This approach is called static polymorphism, because it is determined at compile time which function to call.

Example of polymorphism through function overloading:

#include <iostream>
using namespace std;

void printNumber(int num) {
    cout << "Integer number: " << num << endl;
}

void printNumber(double num) {
    cout << "Floating-point number: " << num << endl;
}

int main() {
    int i = 10;
    double d = 3.14;

    printNumber(i); // 输出:"Integer number: 10"
    printNumber(d); // 输出:"Floating-point number: 3.14"

    return 0;
}

4. Function templates (function templates): By using template parameters to accept different types of parameters, so as to achieve static polymorphism. The compiler will automatically generate a suitable function according to the parameter type passed in when calling.

Example of polymorphism through function templates:

#include <iostream>
using namespace std;

template <typename T>
T maximum(T a, T b) {
    return (a > b) ? a : b;
}

int main() {
    int i1 = 5, i2 = 10;
    double d1 = 3.14, d2 = 2.71;

    cout << "Maximum of two integers: " << maximum(i1, i2) << endl;       // 输出:10
    cout << "Maximum of two floating-point numbers: " << maximum(d1, d2) << endl; // 输出:3.14

    return 0;
}

The above mentioned are the main polymorphic implementations in C++.

appendix

C++ virtual function, pure virtual function https://zhuanlan.zhihu.com/p/37331092

C++ abstract class https://zhuanlan.zhihu.com/p/266311842

C++ polymorphism can be seen in the relevant part of the article "C++ Object-Oriented Programming (Part 2)" https://blog.csdn.net/cnds123/article/details/109602105

Guess you like

Origin blog.csdn.net/cnds123/article/details/131832675