网站导航栏字体,旅游设计专业网站,百度推广获客成本大概多少,网站建设优势概念
C中的多态性是面向对象编程的一个重要特征#xff0c;它允许我们通过一个基类的指针或引用来操作不同派生类的对象。多态性增强了代码的灵活性和可扩展性。主要分为两种类型#xff1a;编译时多态#xff08;静态多态#xff09;和运行时多态#xff08;动态多态中的多态性是面向对象编程的一个重要特征它允许我们通过一个基类的指针或引用来操作不同派生类的对象。多态性增强了代码的灵活性和可扩展性。主要分为两种类型编译时多态静态多态和运行时多态动态多态。
编译时多态静态多态
编译时多态通常通过函数重载和运算符重载实现。编译器在编译时决定调用哪个函数。
#include iostream
using namespace std; class Print {
public: void display(int i) { cout Displaying integer: i endl; } void display(double d) { cout Displaying double: d endl; }
}; int main() { Print p; p.display(5); // 调用display(int) p.display(5.5); // 调用display(double) return 0;
}运行时多态动态多态
运行时多态通过虚函数实现允许在运行时根据对象的实际类型调用相应的函数。当我们定义一个虚函数并在子类中重写它时基类的指针或引用可以指向子类的对象并根据实际对象的类型调用相应的函数。
#include iostream
using namespace std; class Base {
public: virtual void show() { // 虚函数 cout Base class show function called. endl; } virtual ~Base() {} // 虚析构函数
}; class Derived : public Base {
public: void show() override { // 重写虚函数 cout Derived class show function called. endl; }
}; int main() { Base* basePtr; // 基类指针 Derived derivedObj; // 派生类对象 basePtr derivedObj; // 指向派生类对象 basePtr-show(); // 调用派生类的show() return 0;
}原理
1.虚函数 虚函数是在基类中使用virtual关键字声明的函数用于支持运行时多态。通过虚函数可以在基类中定义接口而在派生类中实现具体的逻辑。当使用基类指针或引用指向派生类对象并调用该虚函数时C会根据对象的真实类型来调用相应的函数实现。
2. 虚表vtable 每个包含虚函数的类在运行时会有一个虚表vtable。这个虚表是一个函数指针数组存储了该类的所有虚函数的地址。当创建一个对象时编译器会为该对象生成一个指向其类虚表的指针称为虚指针vptr。
3. 运行时过程 运行时多态的过程大致如下 1.声明和定义在基类中用virtual关键字声明虚函数在派生类中重写该虚函数。 2.对象创建当基类指针或引用指向派生类对象时派生类对象的虚指针会指向派生类的虚表。
3.函数调用
当通过基类指针或引用调用虚函数时程序会查找对象的虚表找到对应虚函数的地址并执行。这是一个动态过程因为决定调用哪个函数是在运行时而不是编译时。
#include iostream
using namespace std; class Base {
public: virtual void show() { // 虚函数 cout Base class show function called. endl; } virtual ~Base() {} // 虚析构函数
}; class Derived : public Base {
public: void show() override { // 重写虚函数 cout Derived class show function called. endl; }
}; void demonstratePolymorphism(Base* b) { b-show(); // 调用虚函数
} int main() { Base baseObj; // 基类对象 Derived derivedObj; // 派生类对象 demonstratePolymorphism(baseObj); // 调用基类的 show demonstratePolymorphism(derivedObj); // 调用派生类的 show return 0;
}创建基类Base和派生类DerivedDerived重写了Base中的虚函数show。函数demonstratePolymorphism接受基类指针作为参数调用show函数。实际上将根据指针所指向的对象类型来调用相应的版本。当调用show时即使传入的是基类指针实际执行的是派生类的show。
重载重写隐藏
重载Overloading
重载是指在同一作用域内可以定义多个同名函数只要它们的参数列表参数的数量或类型不同就可以。重载发生在同一个类中也可以在继承关系中的不同类中的同名函数。
#include iostream
using namespace std; class Math {
public: // 重载不同参数数量和类型 int add(int a, int b) { return a b; } double add(double a, double b) { return a b; } int add(int a, int b, int c) { return a b c; }
}; int main() { Math math; cout math.add(1, 2) endl; // 调用 add(int, int) cout math.add(1.5, 2.5) endl; // 调用 add(double, double) cout math.add(1, 2, 3) endl; // 调用 add(int, int, int) return 0;
}在上面的例子中add函数被重载具有不同的参数类型和数量。
重写Overriding
重写是指在派生类中重新定义基类中已经声明的虚函数。重写允许派生类为基类的虚函数提供特定的实现。重写是在继承关系中发生的它通常涉及到基类的虚函数和派生类的同名函数。
#include iostream
using namespace std; class Base {
public: virtual void show() { // 虚函数允许重写 cout Base class show function. endl; }
}; class Derived : public Base {
public: void show() override { // 重写基类的虚函数 cout Derived class show function. endl; }
}; int main() { Base* basePtr; Derived derived; basePtr derived; basePtr-show(); // 调用 Derived::show() return 0;
}在这段代码中Derived类中的show函数重写了Base类中的虚函数show。通过基类指针调用时会执行派生类的实现。
隐藏Hiding
隐藏是指在派生类中定义一个与基类中同名的成员可以是函数或变量这会遮蔽基类中的所有同名成员。隐藏不是重载也不是重写它发生在同一作用域内并且会隐藏基类中的所有同名函数和变量不论其参数和返回类型。
#include iostream
using namespace std; class Base {
public: void func(int i) { cout Base func with int: i endl; } void func(double d) { cout Base func with double: d endl; }
}; class Derived : public Base {
public: void func(int i) { // 该函数隐藏了 Base 中的所有 named func cout Derived func with int: i endl; }
}; int main() { Derived d; d.func(10); // 调用 Derived::func(int) // d.func(3.14); // 错误Base::func(double) 被隐藏不能调用 return 0;
}在这个例子中Derived类中的func(int)函数隐藏了Base类中的所有同名成员函数尽管基类中还有一个func(double)。因此尝试调用d.func(3.14)将导致编译错误。
总结
重载Overloading同一个作用域中可以有多个同名函数参数列表不同。重写Overriding在派生类中重新定义基类中的虚函数允许多态。隐藏Hiding在派生类中定义与基类中同名的成员遮蔽基类中的所有同名成员。