美文网首页
C++中的四种多态

C++中的四种多态

作者: 雪域迷影 | 来源:发表于2021-02-26 23:59 被阅读0次

本文转载自The Four Polymorphisms in C++

C++中的四种多态

当人们谈论C ++中的多态性时,通常是指通过基类指针或引用使用派生类的事情,这称为子类型多态性。 但是他们经常忘记,C ++中还有各种各样的其他多态性,例如参数多态性ad-hoc多态性强制多态性

这些多态性在C ++中也有不同的名称,
- 子类型多态也称为运行时多态。
- 参数多态也称为编译时多态。
- 临时多态性也称为重载。
- 强制转换也称为(隐式或显式)强制转换。
在本文中,我将通过C ++语言的示例来说明所有多态性,并深入介绍为什么它们具有其他各种名称。

子类型多态性(运行时多态子类型多态是每个人在C ++中说“多态”时所理解的。 通过基类指针和引用使用派生类的能力。

这是一个例子。 假设您有各种猫科动物,例如这些猫科动物,


polymorphic-cats.gif

由于它们都是Felidae的生物学家族,并且都应该能够喵叫,因此可以将它们表示为从Felid基类继承并覆盖meow纯虚拟功能的类,

// file cats.h

class Felid {
public:
 virtual void meow() = 0;
};

class Cat : public Felid {
public:
 void meow() { std::cout << "Meowing like a regular cat! meow!\n"; }
};

class Tiger : public Felid {
public:
 void meow() { std::cout << "Meowing like a tiger! MREOWWW!\n"; }
};

class Ocelot : public Felid {
public:
 void meow() { std::cout << "Meowing like an ocelot! mews!\n"; }
};

现在,主程序可以通过Felid(基类)指针互换使用CatTigerOcelot

#include <iostream>
#include "cats.h"

void do_meowing(Felid *cat) {
 cat->meow();
}

int main() {
 Cat cat;
 Tiger tiger;
 Ocelot ocelot;

 do_meowing(&cat);
 do_meowing(&tiger);
 do_meowing(&ocelot);
}

在这里,主程序将指向cattigerocelot的指针传递给do_meowing函数,该函数期望指向Felid的指针。 由于它们都是猫科动物,因此程序会为每个猫科动物调用正确的meow函数,并且输出为:

Meowing like a regular cat! meow!
Meowing like a tiger! MREOWWW!
Meowing like an ocelot! mews!

由于种种原因,子类型多态也称为运行时多态。 多态函数调用的解析是在运行时通过虚拟表通过间接进行的。 另一种解释方式是,编译器不在编译时定位要调用的函数的地址,而是在程序运行时通过在虚拟表中取消引用右指针来调用该函数。

在类型理论中,它也称为包含多态性

参数多态性(编译时多态性)

参数多态性提供了一种对任何类型执行相同代码的方法。 在C ++中,参数多态性是通过模板实现的。

最简单的示例之一是泛型max函数,该函数找到两个参数中的最大值,

#include <iostream>
#include <string>

template <class T>
T max(T a, T b) {
 return a > b ? a : b;
}

int main() {
 std::cout << ::max(9, 5) << std::endl;     // 9

 std::string foo("foo"), bar("bar");
 std::cout << ::max(foo, bar) << std::endl; // "foo"
}

在这里,max函数在类型T上是多态的。但是,请注意,它不适用于指针类型,因为比较指针会比较内存位置而不是内容。 为了使它适用于指针,您必须专门针对指针类型使用模板,该模板不再是参数多态性,而是ad-hoc多态性。

由于参数多态性是在编译时发生的,因此也称为编译时多态性

临时多态性(重载)

临时多态性允许具有相同名称的函数对于每种类型的行为有所不同。 例如,给定两个整数和+运算符,它将它们加在一起。 给定两个std::strings,将它们连接在一起。 这称为重载

这是一个为intstring实现函数add的具体示例,

#include <iostream>
#include <string>

int add(int a, int b) {
 return a + b;
}

std::string add(const char *a, const char *b) {
 std::string result(a);
 result += b;
 return result;
}

int main() {
 std::cout << add(5, 9) << std::endl;
 std::cout << add("hello ", "world") << std::endl;
}

如果您专门研究模板,则临时多态性也会在C ++中出现。 返回上一个有关max函数的示例,这是您如何为两个char *编写max的方法,

template <>
const char *max(const char *a, const char *b) {
 return strcmp(a, b) > 0 ? a : b;
}

现在,您可以调用::max(“ foo”,“ bar”)来查找字符串“ foo”和“ bar”的最大值。

强制多态性(转换)

当将一个对象或原始类型强制转换为另一个对象类型或原始类型时,会发生强制转换。 例如,

float b = 6; // int gets promoted (cast) to float implicitly
int a = 9.99 // float gets demoted to int implicitly

当使用C的类型转换表达式,例如(unsigned int *)(int)或C ++的static_castconst_castreinterpret_castdynamic_cast时,会发生显式转换。

如果类的构造函数不是explicit的,则也会发生强制转换,例如,

#include <iostream>

class A {
 int foo;
public:
 A(int ffoo) : foo(ffoo) {}
 void giggidy() { std::cout << foo << std::endl; }
};

void moo(A a) {
 a.giggidy();
}

int main() {
 moo(55);     // prints 55
}

如果将A的构造函数设为explict,则将不再可能。 使构造函数显式以避免意外转换始终是一个好主意。

同样,如果类为T类型定义了转换运算符,则可以在需要T类型的任何地方使用它。

例如,

class CrazyInt {
 int v;
public:
 CrazyInt(int i) : v(i) {}
 operator int() const { return v; } // conversion from CrazyInt to int
};

CrazyInt定义了一个转换运算符来键入int。 现在,如果我们有一个以int作为参数的print_int函数,我们还可以将CrazyInt类型的对象传递给它,

#include <iostream>

void print_int(int a) {
 std::cout << a << std::endl;
}

int main() {
 CrazyInt b = 55;
 print_int(999);    // prints 999
 print_int(b);      // prints 55
}

我前面讨论的子类型多态实际上也是强制性多态,因为派生类已转换为基类类型。

玩弄所有有关多态性的新知识,下次再见!

相关文章

  • C++中的四种多态

    本文转载自The Four Polymorphisms in C++[https://catonmat.net/c...

  • Swift 多态实现探究

    多态 父类指针指向子类对象 Swift 中多态的实现类似于 c++ 中的虚表 OC 多态实现利用的是 Runtim...

  • 深刻剖析之c++博客文章

    三大特性 封装、继承、多态 多态 C++ 虚函数表解析C++多态的实现原理 介绍了类的多态(虚函数和动态/迟绑定)...

  • C++第六篇多态

    C++中的多态性分为编译时多态性和运行时多态性,编译时多态通过函数重载和模板体现,运行多态通过虚函数体现编译、连接...

  • C++学习笔记(面向对象)

    C++是一门面向对象的语言 类定义 & 对象 C++ 中的继承,多态,抽象

  • C++中多态

    多态成立的三个条件 有继承 有函数重写 有父类指针(父类引用)指向子类对象 多态原理 当类中声明虚函数时,编译器会...

  • C++ 中的多态

    首先说一个基本例子: //人类 class Human{public: void say(){ cout << "...

  • C++中的多态

    姓名:刘亚宁 学号:17101223434 转载自:http://blog.csdn.net/zybqmy/a...

  • C++编译期多态和运行期多态

    C++多态有多种实现方式,在面对对象编程时,采用的是运行期多态,也称动态多态。在泛型编程中,多态基于模板的具现化与...

  • Go interface详解

      如Go method中提及,Golang没有明确支持多态,但是通过其他手段可以实现类似C++中的多态特性,即本...

网友评论

      本文标题:C++中的四种多态

      本文链接:https://www.haomeiwen.com/subject/exkbfltx.html