接口与纯虚类的区别

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了接口与纯虚类的区别相关的知识,希望对你有一定的参考价值。

和问题一样

参考技术A

1.相同点

  A. 两者都是抽象类,都不能实例化。

  B. interface实现类及abstrct class的子类都必须要实现已经声明的抽象方法。

2. 不同点

  A. interface需要实现,要用implements,而abstract class需要继承,要用extends。

  B. 一个类可以实现多个interface,但一个类只能继承一个abstract class。

  C. interface强调特定功能的实现,而abstract class强调所属关系。 

  D. 尽管interface实现类及abstrct class的子类都必须要实现相应的抽象方法,但实现的形式不同。interface中的每一个方法都是抽象方法,都只是声明的 (declaration, 没有方法体),实现类必须要实现。而abstract class的子类可以有选择地实现。

  这个选择有两点含义:

    一是Abastract class中并非所有的方法都是抽象的,只有那些冠有abstract的方法才是抽象的,子类必须实现。那些没有abstract的方法,在Abstrct class中必须定义方法体。

    二是abstract class的子类在继承它时,对非抽象方法既可以直接继承,也可以覆盖;而对抽象方法,可以选择实现,也可以通过再次声明其方法为抽象的方式,无需实现,留给其子类来实现,但此类必须也声明为抽象类。既是抽象类,当然也不能实例化。

  E. abstract class是interface与Class的中介。

  interface是完全抽象的,只能声明方法,而且只能声明pulic的方法,不能声明private及protected的方法,不能定义方法体,也 不能声明实例变量。然而,interface却可以声明常量变量,并且在JDK中不难找出这种例子。但将常量变量放在interface中违背了其作为接 口的作用而存在的宗旨,也混淆了interface与类的不同价值。如果的确需要,可以将其放在相应的abstract class或Class中。

  abstract class在interface及Class中起到了承上启下的作用。一方面,abstract class是抽象的,可以声明抽象方法,以规范子类必须实现的功能;另一方面,它又可以定义缺省的方法体,供子类直接使用或覆盖。另外,它还可以定义自己 的实例变量,以供子类通过继承来使用。

3. interface的应用场合

  A. 类与类之前需要特定的接口进行协调,而不在乎其如何实现。

  B. 作为能够实现特定功能的标识存在,也可以是什么接口方法都没有的纯粹标识。

  C. 需要将一组类视为单一的类,而调用者只通过接口来与这组类发生联系。

  D. 需要实现特定的多项功能,而这些功能之间可能完全没有任何联系。

4. abstract class的应用场合

  一句话,在既需要统一的接口,又需要实例变量或缺省的方法的情况下,就可以使用它。最常见的有:

  A. 定义了一组接口,但又不想强迫每个实现类都必须实现所有的接口。可以用abstract class定义一组方法体,甚至可以是空方法体,然后由子类选择自己所感兴趣的方法来覆盖。

  B. 某些场合下,只靠纯粹的接口不能满足类与类之间的协调,还必需类中表示状态的变量来区别不同的关系。abstract的中介作用可以很好地满足这一点。

  C. 规范了一组相互协调的方法,其中一些方法是共同的,与状态无关的,可以共享的,无需子类分别实现;而另一些方法却需要各个子类根据自己特定的状态来实现特定的功能。

首先接口是一种高度抽象的"模版",,而接口中的属性也就是’模版’的成员,就应当是所有实现"模版"的实现类的共有特性,所以它是public static的 ,是所有实现类共有的 .假如可以是非static的话,因一个类可以继承多个接口,出现重名的变量,如何区分呢?

 

其次,接口中如果可能定义非final的变量的话,而方法又都是abstract的,这就自相矛盾了,有可变成员变量但对应的方法却无法操作这些变量,虽然可以直接修改这些静态成员变量的值,但所有实现类对应的值都被修改了,这跟抽象类有何区别? 又接口是一种更高层面的抽象,

是一种规范、功能定义的声明,所有可变的东西都应该归属到实现类中,这样接口才能起到标准化、规范化的作用。所以接口中的属性必然是final的

参考技术B c++虚类相当与java里面的抽象类,与接口的不同之处如下:
1、一个子类只能继承一个抽象类(虚类),但能实现多个接口;
2、一个抽象类可以有构造方法,接口没有构造方法;
3、一个抽象类中的方法不一定是抽象方法,即其中的方法可以有实现(有方法体),接口中的方法都是抽象方法,不能有方法体,只有声明;
4、一个抽象类可以是public、private、protected、default,
接口只有public,default;
5、一个抽象类中的方法可以是public、private、protected、default,
接口中的方法只能是public和default.

相同之处:都不能实例化。
补充说明:接口是一类特殊的抽象类,是更抽象的抽象类,你可能这样理解。抽象类是一个不完整的类,接口只是定义了一些功能。打个比方,用抽象类和接口分别描述“猪”,抽象类就是在一般的类之前加abstrict,说:猪能用四肢跑,猪还能怎么怎么,接口的话只能说,猪会跑,用什么跑就是子类的事啦。

多态实现--虚函数与纯虚函数

多态实现--虚函数与纯虚函数

  • C++中实现多态是使用虚函数表的方法实现的。
  • 那么具体怎么实现的呢?

举例说明

  • 假设有这样一个多态场景:
  • 有一个基类动物(animal类),动物里面又有两个派生类:猫(cat类)和狗(dog类)。现在要求动物类有一个共同的方法:叫声(voice成员函数),但猫和狗叫声是不同的(即:它们的叫声实现方法不同)。
  • 那么代码怎么写呢?

多态的代码实现

#include <iostream>
using namespace std;

//1、 定义一个纯虚函数
class animal
{
public:
    virtual void voice()= 0;    //纯虚函数voice
};

//2、 定义猫(cat)狗(dog)类,共同继承自animal,但对voice进行了具体实现
class cat:public animal
{
public:
    virtual void voice()
    {
        cout <<"喵喵喵"<<endl;
    }
};

class dog:public animal
{
public:
    virtual void voice()
    {
        cout <<"汪汪汪"<<endl;
    }
};

//3、那么下一步就要给猫和狗做一个统一接口了,传参用基类指针。这个接口只有一个功能,就是调用动物叫声voice。
void animal_voice(animal * a)
{
    a->voice();
}

//4、 多态写好了,我们来调用一下试试,写个test看看这个多态有没有问题。我们分别定义一个猫狗对象,来调用统一接口,看看它们的叫声是否相同。

void test()
{
    cat c;
    dog d;
    animal_voice(&c);
    animal_voice(&d);
}

int main()
{
    test();
    return 0;
}
  • 验证结果:

    喵喵喵
    汪汪汪

说明这个多态已实现完成。

多态原理

  • 那么多态的原理是怎么样的呢?为什么这样写代码,就能实现猫和狗叫声不同,它们明明调用的是同一个接口呀?

  • 我们知道C++在编译时为我们做了很多背后的工作。它为cat和dog分别生成了一张虚函数表,将函数地址(也就是函数指针)记录在各自的虚函数表中。如图所示。

    • cat的虚函数表:
cat的虚函数表
cat的voice函数的地址
- dog的虚函数表:
dog的虚函数表
dog的voice函数的地址
  • 这样当我们用接口调用cat和dog的voice函数时,它们会各自在自己的虚函数表里找到自己的voice函数地址,然后根据这个地址来进行调用了。怎么样,多态实现很简单吧?

虚函数与纯虚函数

  • 那么animal里的纯虚函数virtual void voice()= 0;只能这样写吗?它可以像下面这样写成虚函数吗?
    ```
    virtual void voice()
    {

}
```

  • 答案是可以,但它们是不同的。这里的虚函数是有实现的,只是它的实现方法是空,那么在cat和dog中我们再次实现这个voice就相当于重写(也就是说,我们也可以选择省略(即:不重写)这个voice)。但如果写成纯虚函数,那么我们就必须要在cat和dog中具体实现voice。

  • 也就是这里的虚函数是有这个函数的实现,只是为空;而纯虚函数是这个函数根本还没实现。

以上是关于接口与纯虚类的区别的主要内容,如果未能解决你的问题,请参考以下文章

虚函数与纯虚函数

虚析构函数与纯虚函数

Java的接口和C++的虚类的相同和不同处?

虚函数和纯虚函数的区别

虚函数和纯虚函数的区别

C++ 虚函数和纯虚函数的区别