多态性和遗传性有什么区别

what is the difference between polymorphism and inheritance

本文关键字:什么 区别 遗传性 多态性      更新时间:2023-10-16

我对继承和多态的概念感到困惑。我的意思是,代码重用性和函数覆盖有什么区别?是不可能使用继承概念重用父类函数,还是不可能使用多态性覆盖父类变量。对我来说似乎没有什么区别。

 class A
{
  public:
      int a;
      virtual void get()
      {
        cout<<"welcome";
      }
};
class B:public A
{
  a =a+1; //why it is called code reuse
  void get() //why it is called overriding
 {
    cout<<"hi";
 }
};

我的疑问是关于代码重用和函数覆盖之间的区别。

让我们从您的示例开始。

class A
{
  public:
      int a;
      virtual void get()
      {
        cout<<"welcome";
      }
};
class B:public A
{
  a =a+1; //why it is called code reuse
  void get() //why it is called overriding
 {
    cout<<"hi";
 }
};

继承:这里你从类 A 派生 B 类,这意味着你可以访问它的所有公共变量和方法。

a = a + 1

在这里,您使用的是class A的变量a,您将在class B中重用变量a,从而实现代码的可重用性。

多态性处理程序如何根据它必须执行的操作调用方法:在您的示例中,您将使用class B的方法get()覆盖class A的方法get()。因此,当您创建类 B 的实例并调用方法 get 时,您将在控制台中得到'hi',而不是'welcome'

函数继承允许将行为从"更具体"的派生类抽象为"更抽象"的基类。 (这类似于在基础数学和代数中分解。 在这种情况下,更抽象只是意味着指定更少的细节。 预计派生类将扩展(或添加)基类中指定的内容。 例如:

class CommonBase
{
    public:
        int getCommonProperty(void) const  { return m_commonProperty; }
        void setCommonProperty(int value)  { m_commonProperty = value; }
    private:
        int m_commonProperty;
};
class Subtype1 : public CommonBase
{
    // Add more specific stuff in addition to inherited stuff here...
    public:
        char getProperty(void) const { return m_specificProperty1; }
    private:
        char m_specificProperty1;
};
class Subtype2 : public CommonBase
{
    // Add more specific stuff in addition to inherited stuff here...
    public:
        float getProperty(void) const { return m_specificProperty2; }
    private:
        float m_specificProperty2;
};

请注意,在上面的示例中,getCommonProperty()setCommonProperty(int) 继承自 CommonBase 类,并且可以在类型为 Subtype1Subtype2 的对象实例中使用。 所以我们在这里有继承,但我们还没有真正的多态性(如下所述)。

您可能希望也可能不希望实例化基类的对象,但您仍然可以使用它来收集/指定所有派生类将继承的行为(方法)和属性(字段)。 因此,关于代码重用,如果您有多种类型的派生类共享一些常见行为,则可以在基类中仅指定一次该行为,然后在所有派生类中"重用"该行为,而无需复制它。 例如,在上面的代码中,getCommmonProperty()setCommonProperty(int)的规范可以说是每个Subtype#类重用的,因为不需要为每个类重写方法。

多态性是相关的,但它意味着更多。 这基本上意味着您可以以相同的方式处理碰巧来自不同类的对象,因为它们都恰好派生自(扩展)公共基类。 为了使这真正有用,该语言应该支持虚拟继承。 这意味着函数签名在多个派生类中可以是相同的(即,签名是通用抽象基类的一部分),但会根据特定类型的对象执行不同操作。

因此,修改上面的示例以添加到CommonBase(但保持Subtype1Subtype2与以前相同):

class CommonBase
{
    public:
        int getCommonProperty(void) const  { return m_commonProperty; }
        void setCommonProperty(int value)  { m_commonProperty = value; }
        virtual void doSomething(void) = 0;
        virtual ~CommonBase() { }
    private:
        int m_commonProperty;
};

请注意,doSomething()在这里声明为 CommonBase 中的纯虚函数(这意味着您永远不能直接实例化CommonBase对象 - 它不必是这种方式,我只是为了保持简单)。 但是现在,如果你有一个指向CommonBase对象的指针,它可以是Subtype1Subtype2,你可以调用doSomething()。 这将根据对象的类型执行不同的操作。 这就是多态性。

void foo(void)
{
    CommonBase * pCB = new Subtype1;
    pCB->doSomething();
    pCB = new Subtype2;
    pCB->doSomething();      // Does something different... 
}

就您在问题中提供的代码示例而言,get()之所以称为"重写",是因为如果您在B对象的实例上调用get(),则该方法B::get()版本中指定的行为优先于("覆盖")该方法A::get()版本中指定的行为(即使您通过 A* 执行此操作, 因为该方法在类 A 中声明为virtual)。

最后,您

关于"代码重用"的其他评论/问题并没有像您指定的那样完全有效(因为它不在方法中),但我希望如果您参考我上面写的内容,它会很清楚。 当您从公共基类继承行为并且只需为该行为编写一次代码(在基类中),然后所有派生类都可以使用它时,这可以被视为一种"代码重用"。

您可以在没有继承的情况下具有参数化多态性。在C++中,这是使用模板实现的。维基文章:

http://en.wikipedia.org/wiki/Polymorphism_%28computer_science%29#Parametric_polymorphism