C++学习笔记——多态与静态联编和动态联编

发布时间:2024年01月12日

目录

一、多态

二、静态联编(Static Binding)和动态联编(Dynamic Binding)

2.1静态联编

2.2动态联编


一、多态

是C++中面向对象编程的一个核心概念,它允许派生类对象替代其基类对象,从而实现代码重用和扩展。公有继承是一种实现多态性的方式。

公有继承是指在派生类中定义了与基类中同名的成员函数,当使用基类指针或引用调用该函数时,实际调用的是派生类中的版本。这种行为被称为函数重写(Function Overriding)或运行时多态性(Run-time Polymorphism)。

以下是一个简单的示例,演示了公有继承的多态特性:

#include <iostream>

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

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

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

    animal->makeSound();  // 输出 "Animal makes a sound."
    dog->makeSound();     // 输出 "Dog barks."

    Animal* animal2 = dog;
    animal2->makeSound(); // 输出 "Dog barks."

    delete animal;
    delete dog;

    return 0;
}

在这个示例中,我们定义了一个基类Animal和一个派生类Dog。基类中有一个虚函数makeSound,它被派生类重写。在main函数中,我们创建了一个基类对象和一个派生类对象,并通过它们分别调用makeSound方法。此时,基类对象调用的是基类中的版本,而派生类对象调用的是派生类中的版本。

接着,我们将派生类对象的地址赋给了一个基类指针,然后通过该指针调用makeSound方法。由于makeSound方法是虚函数,因此编译器会在运行时根据实际对象类型来确定要调用哪个版本的函数,这种行为被称为多态性。

二、静态联编(Static Binding)和动态联编(Dynamic Binding)

是C++中用于确定函数调用的两种不同的机制。

2.1静态联编

是在编译时确定函数调用的机制。它根据函数调用的静态类型来确定要调用的函数版本。静态类型是指在编译时已知的变量或表达式的类型。静态联编是默认的绑定机制,适用于非虚函数和全局函数。

以下是一个示例,演示了静态联编的行为:

#include <iostream>

class Animal {
public:
    void makeSound() {
        std::cout << "Animal makes a sound." << std::endl;
    }
};

class Dog : public Animal {
public:
    void makeSound() {
        std::cout << "Dog barks." << std::endl;
    }
};

int main() {
    Animal animal;
    Dog dog;

    Animal* animalPtr = &animal;
    Animal* dogPtr = &dog;

    animalPtr->makeSound(); // 输出 "Animal makes a sound."
    dogPtr->makeSound();    // 输出 "Animal makes a sound."

    return 0;
}

在这个示例中,我们定义了一个基类Animal和一个派生类Dog,它们都有一个名为makeSound的函数。在main函数中,我们创建了一个基类对象和一个派生类对象,并将它们分别赋值给基类指针animalPtrdogPtr。然后,我们通过这两个指针调用makeSound方法。

由于静态联编是根据指针的静态类型来确定函数版本,因此无论使用哪个指针调用makeSound方法,都会调用基类中的版本,而不会调用派生类中的版本。

相比之下

2.2动态联编

是在运行时确定函数调用的机制。它根据函数调用的实际对象类型来确定要调用的函数版本。动态联编适用于虚函数和通过基类指针或引用调用的成员函数。

以下是一个示例,演示了动态联编的行为:

#include <iostream>

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

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

int main() {
    Animal animal;
    Dog dog;

    Animal* animalPtr = &animal;
    Animal* dogPtr = &dog;

    animalPtr->makeSound(); // 输出 "Animal makes a sound."
    dogPtr->makeSound();    // 输出 "Dog barks."

    return 0;
}

在这个示例中,我们将makeSound函数声明为虚函数,并使用override关键字在派生类中重写该函数。在main函数中,我们创建了一个基类对象和一个派生类对象,并将它们分别赋值给基类指针animalPtrdogPtr。然后,我们通过这两个指针调用makeSound方法。

由于动态联编是根据指针所指向的实际对象类型来确定函数版本,因此使用基类指针调用makeSound方法时,会根据实际对象类型来决定是调用基类中的版本还是派生类中的版本。在这个示例中,基类指针调用makeSound方法时,会根据实际指向的对象来调用相应的函数版本。

总结起来,静态联编是在编译时确定函数调用的机制,根据静态类型来决定调用哪个函数版本;而动态联编是在运行时确定函数调用的机制,根据实际对象类型来决定调用哪个函数版本。虚函数和通过基类指针或引用调用的成员函数使用动态联编。

文章来源:https://blog.csdn.net/m0_62338174/article/details/135563559
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。