【问题标题】:Practical advantage of using polymorphism over inheritance in C++ [closed]在 C++ 中使用多态性优于继承的实际优势 [关闭]
【发布时间】:2019-06-26 11:15:10
【问题描述】:

在 C++ 中使用多态性与仅使用继承相比有什么优势,因为在我看来,使用多态性我无法实现仅使用继承无法做到的事情。同样在这两种方式中,我都可以使用虚拟功能。是否存在多态性可以做一些仅使用继承无法实现的情况?

这两个例子(第一个 - 多态性,第二个 - 单纯继承)让我达到了相同的结果,所以我想知道 polymphism 还能为我提供什么,而这是通过正常继承无法实现的。

多态代码:

#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();
}

我的问题是关于为什么要使用多态性,什么时候可以很好地避免使用它,并限制自己只使用继承。正如 user463035818 所说,基本上不存在多态性可以做一些使用继承无法实现的事情。所以据我了解,使用多态是首选的设计模式?

【问题讨论】:

  • 动态多态性是通过继承实现的。我不明白这个问题。
  • 如果您向我们展示同一问题的两种解决方案会更容易,一种使用(您称之为)多态性,另一种使用(您称之为)继承。
  • 请为每种情况提供一个示例 sn-p,以便我们更好地了解您要比较的两种情况。 (对我来说,它们是一样的)
  • 你的意思是composition over inheritance?不,显然不会重读。我和其他人一起困惑。
  • 我知道多态是通过继承实现的。然而,我问我还能用多态性做什么,而仅仅通过继承是不可能的。

标签: c++ inheritance polymorphism


【解决方案1】:

至少在 C++ 中,使用继承的主要原因是多态性。还有一种叫做“实现继承”的东西,但它作为一般规则是不受欢迎的。

多态性的典型例子包括一个虚函数,它在基类中声明并在派生类中实现:

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

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

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

实现继承主要适用于您有许多派生类的情况,这些派生类都对相同的通用事物进行细微的变化,因此您可以在案例类中实现共同的行为,并且每个派生类只实现其中的区域它与那个共同的基础不同。

在 C++ 中实现继承的一个众所周知的例子是std::iterator。这是一个包含虚函数的基类(因此没有多态性)。它的唯一目的是提供一些迭代器应该提供的typedefs。这些类型通常都是相关的,因此派生类通常可以将单个模板参数传递给基类,并获取所有必要的typedefs:

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

这使迭代器的实现者免于键入如下代码: 使用 size_type = std::size_t; 使用差异类型 = std::ptr_diff_t; 使用 value_type = T; 使用参考 = T&; 使用指针 = T*;

它确实节省了一些打字——但不是很多,而且它节省的几乎都是简单的样板。

然而,如上所述,这通常是不被接受的——事实上,std::iterator 已被正式弃用,因此它可能会从标准的某些未来版本中消失。

【讨论】:

    【解决方案2】:

    多态性

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

    例如:

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

    不同的类型可以继承同一个基类,这样它们就可以多态地使用。

    是否存在多态性可以做一些不能做的事情的情况 可以通过继承访问吗?

    没有。

    嗯....是的。

    模板的一些用法可以被认为是编译时多态性。如果你对编译时多态感兴趣,你应该看看CRTP

    【讨论】:

      猜你喜欢
      • 2011-11-04
      • 2011-05-20
      • 1970-01-01
      • 2015-01-02
      • 1970-01-01
      • 2012-08-08
      • 2011-08-17
      • 2010-12-18
      • 2014-02-27
      相关资源
      最近更新 更多