在C ++中使用多态性而非继承的实际优势

时间:2019-02-01 20:45:29

标签: c++ inheritance polymorphism

在C ++中使用多态性比仅使用继承有什么优势,因为在我看来,用多态性无法实现我仅靠继承无法做到的事情。同样,我可以通过两种方式使用虚函数。是否存在仅使用继承就无法完成多态的事情?

这两个例子(第一个-多态性,第二个-纯继承性)使我获得了相同的结果,因此我想知道,多态性还可以为我提供什么,而普通继承不能做到这一点。

多态代码:

#include <iostream>
using namespace std;
class Kryptonians
{
public:
    void setPower(int p) {power = p;}
    void gotHit(int h){power -=h;}
    virtual void displayPower(){std::cout << "power is: " << power << "\n";}

protected:
    int power;
};

class Supergirl: public Kryptonians
{
public:
   void displayPower(){
       std::cout << "Supergirl's power is: " << power << "\n";}
};

class Superman: public Kryptonians
{
public:
    void displayPower(){
        std::cout << "Superman's power is: " << power << "\n";}
};

int main()
{
    Supergirl sup;
    Superman super;
    Kryptonians *supergirl = &sup;
    Kryptonians *superman = &super;

    supergirl->setPower(100);
    supergirl->displayPower();

    superman->setPower(100);
    superman->gotHit(50);
    superman->displayPower();
    supergirl->displayPower();
}

仅仅是淫荡代码:

#include <iostream>
using namespace std;
class Kryptonians
{
public:
    void setPower(int p) {power = p;}
    void gotHit(int h){power -=h;}
    virtual void displayPower(){std::cout << "power is: " << power << "\n";}

    protected:
    int power;
};

class Supergirl: public Kryptonians
{
public:
    void displayPower(){
        std::cout << "Supergirl's power is: " << power << "\n";}
};

class Superman: public Kryptonians
{
public:
    void displayPower(){
        std::cout << "Superman's power is: " << power << "\n";}
};

int main()
{
    Supergirl supergirl;
    supergirl.setPower(100);
    supergirl.displayPower();

    Superman superman;
    superman.setPower(100);
    superman.gotHit(50);
    superman.displayPower();

    supergirl.displayPower();
}

我的问题是为什么在完全可以避免使用多态的情况下完全使用多态,并限制自己仅使用继承。如用户463035818所述,从根本上讲,多态不能做某些无法通过使用继承来实现的事情。因此,据我了解,首选使用多点模式?

2 个答案:

答案 0 :(得分:2)

至少在C ++中,使用继承的主要原因是多态性。还有一种叫做“实现继承”的东西,但是作为一般规则,人们对此并不满意。

多态性的典型示例将涉及一个虚函数,该虚函数在基类中声明并在派生类中实现:

class interface { 
public:
    virtual void foo() = 0;
};

class implementation : public interface { 
public:
    virtual void foo() override {
        // do something useful here
    }
};

在这种情况下,基类实际上根本没有实现foo,而只是声明了一个接口,因此任何与该接口一起使用的代码都可以与该基类的任何派生类一起使用。

实现继承主要适用于以下情况:您有多个派生类,它们对相同的一般事物都做了细微的变化,因此您可以在case类中实现常见的行为,并且每个派生类仅实现其中的区域它不同于那个共同的基础。

在C ++中,一个非常著名的实现继承示例是std::iterator。这是一个包含虚函数的基类(因此没有多态性)。唯一的目的是提供一些期望迭代器提供的typedef。这些类型通常都是相关的,因此派生类通常可以将单个模板参数传递给基类,并获取所有必需的typedef

class my_iterator : public std::iterator<std::output_iterator_tag, void, void, void, void> {
    // ...
};

这样可以避免迭代器的实现者键入如下代码:     使用size_type = std :: size_t;     使用difference_type = std :: ptr_diff_t;     使用value_type = T;     使用参考= T&;     使用指针= T *;

它确实节省了一些打字操作-但不是很多,而且它保存的几乎是所有简单的样板。

但是,如上所述,这通常是不受欢迎的-实际上,std::iterator已正式弃用,因此它可能会在该标准的将来版本中消失。

答案 1 :(得分:0)

多态

  

在计算机科学中,多态是一种编程语言功能   允许统一处理不同数据类型的值   方式。

例如:

void foo(bar& b) {
   b.do_something();
};

处理相同类型的不同对象称为多态性。 b可以是任何类型,只要它继承bar

继承

  

继承是面向对象编程中的系统,它允许   对象来支持由前部类型定义的操作,而无需   提供自己的定义。它是   面向对象编程中的多态性

例如:

struct bar {
    virtual void do_something() = 0;
    virtual ~bar(){}
};

struct foobar1 : bar {
    virtual void do_something() override {
        std::cout << "muh";
    }
};

struct foobar2 : bar {
    virtual void do_something() override {
        std::cout << "meh";
    }
};

不同的类型可以继承相同的基类,以便可以多态使用它们。

  

是否存在多态可以做某事的情况?   通过继承可以实现?

否。

好吧...是的

tempaltes的某些用法可以视为编译时多态。如果您对编译时的多态性感兴趣,则应该看看CRTP