难道基本上只有一种"种类#34; C ++中的多态性?

时间:2016-04-20 12:40:46

标签: c++ polymorphism overloading

那就是:功能重载

我的意思是

base_ptr->derived_class_method()

基本上是

derived_class_method(base* this_ptr)

是通过函数重载的多态性。

通过模板(包括CRTP等)可以说多态性完全相同。

因此,考虑到最广泛的实施,所有"各种类型"多态性归结为函数重载

或者我错过了什么?

5 个答案:

答案 0 :(得分:4)

  

基本上只有一种“善意”

取决于你如何定义“善意”。 Wikipedia将多态性分为3类:Ad hoc,参数和子类型。所有这些类型的多态性都存在于C ++中。

  

那就是:功能重载

在C ++语言的上下文中,单词function overloading具有特定含义。有了这个含义,模板和虚函数都不能被称为函数重载

然而,抽象地说是,所有多态性(在C ++中,也许在计算机科学中)都归结为选择一个函数实现而不是另一个。

答案 1 :(得分:3)

你缺少一些东西,但主要是一个关键的区别:重载是编译时,而重写(即virtual)可以是运行时。有了重载,你可以这样做:

void make_a_sound(Cat const& cat)
{
  std::cout << cat << ": meow" << std::endl;
}

void make_a_sound(Dog const& dog)
{
  std::cout << dog << ": wurf" << std::endl;
}

int main()
{
  Cat c;
  Dog d;
  make_a_sound(c);
  make_a_sound(d);
}

但你不能这样做:

class Animal
{
  virtual void make_a_sound() = 0;
};

void make_a_sound(std::vector<Animal*> const& animals)
{
  for (Animal* a : animals)
    a->make_a_sound();
}

在第一个示例中,编译器将选择正确的函数以在编译时调用。你可以用不同的方式命名这两个函数(例如make_a_sound_catmake_a_sound_dog)它可以使用相同的名称,只是方便使用相同的名称。

然而,在第二个例子中,编译器生成代码,以便在运行时,您的程序将找出每个动物的确切性质并调用正确的方法。

答案 2 :(得分:2)

基本 多态三种类型:

<强> 1。临时的  2.参数
 3.子类型


1。特设:

Ad-hoc多态性允许具有相同名称的函数对每种类型采取不同的行为。 (这是你给出的例子)

示例:

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;
}

2。参数:

Parametric多态提供了一种为任何类型执行相同代码的方法。它是通过C ++中的模板实现的。 (所以给定定义,你可以说它也是一种自动函数重载)

3。子类型:

通过基类指针和引用使用派生类来实现子类型化。因此,在实际应用中,我们使用子类和虚拟方法进行子类型化。 (这不是函数重载

class Mammal 
{
public:
    Mammal() {};
    virtual ~Mammal() {};

    virtual std::string SendLoudNoise()
    {
        std::string str("I am a generic mammal");
        return str;
    }
};
class Dog : public Mammal {
public:
    Dog() {};
    virtual ~Dog() {};

    std::string SendLoudNoise()
    {
        std::string str("Woof woof!");
        return str;
    }
};
class Cat : public Mammal {
public:
    Cat() {};
    virtual ~Cat() {};

    std::string SendLoudNoise()
    {
        std::string str("--- Twitch my tail ---");
        return str;
    }
};

int main()
{
    Mammal* pAnimal[2] = { new Dog, new Cat};

    for (int i = 0 ; i < 2; ++i)
    {
        std::cout << pAnimal[i]->SendLoudNoise() << std::endl;
        delete pAnimal[i];
    }

    return 0;
}

您无法通过函数重载实现子类型化。因为它是“运行时多态性”。

答案 3 :(得分:0)

C ++中有三个。

主要区别在于“多形体”的独立性。

  • 重载是ad-hoc多态。

它是临时的,因为你只使用相同的名称来表示几个不同的功能,这些功能不需要以任何方式相关。

示例:

int   foo(int);
void  foo(const std::string&, double);
  • 功能模板提供参数多态性。

这些仅取决于其参数的接口(广义上的“接口”;而不是Java的意义)。

示例:

template<typename T>
T id(T t)
{
    return t;
}

如果T是可复制构造的,则为每个T定义一个函数。

要问的一个有效问题是“这不是一种自动重载吗?”,答案就是C ++中的差异并不大。
在其他语言中,id可能只是一个函数,可用于任何类型。

  • “虚拟功能” - 覆盖 - 是子类型。

这些与特定类型层次结构紧密相关。

你会注意到重载需要多态形式有不同的原型,而另外两个需要原型是相同的。

此外,虚函数(通常)在运行时绑定,而其他两个在编译时始终绑定(在C ++中)。

答案 4 :(得分:0)

这里是C ++中所有可能的多态性的完整列表:

  1. ad hoc多态性
    • 强制多态(implizit cast)
    • 重载多态,可以
      • 功能重载
      • 运算符重载
  2. 通用多态性
    • 包含多态(subtyping)
    • 参数或通用多态