C++中抽象类和接口的区别介绍

1. 如果一个类B在语法上继承(extend)了类A, 那么在语义上类B是一个类A.
2. 如果一个类B在语法上实现了(implement)接口I, 那么类B遵从接口I制定的协议.

使用abstract class的根本原因在于, 人们希望通过这样的方式, 表现不同层次的抽象.
而interface的本质是一套协议. 在程序设计的发展中, 人们又发现接口可以用来表示对行为的抽象, 不过, 这只是interface的一种用法不是其本质.

理论结合实际才是最好的学习方式, 不过在这里, 我只想举一些我见到过关于接口使用的反面教材:

1. 在接口中包含数据成员. 这几乎肯定是错的, 因为协议是规范是标准, 不应该跟具体实现有任何牵连, 也不应该给具体实现造成任何负担.
2. C++中 delete 掉一个接口. 例如:


代码如下:

class IInterface()
{
Public:
Virtual ~IInterface(){};

}

Class ClassImpl : public IInterface
{

}

Int main()
{
IInterface* pInterface = new ClassImpl();

delete pInterface;
}

从语法的角度和语言自身的角度来看, 这是可行的, 而且只要将接口的析构函数设置为virtual, 就能避免内存泄漏. 但我要说, 这不是语法和语言的问题, 而是从根本上就错了. 因为接口是一套协议, 一套规范, 并不是实现. Delete 一个接口的代码, 到底想要表达什么样的语义? 如果一段代码从语义上都说不通, 就不应该出现在程序中.
要在C++中表现接口的概念, 一种做法是这样:


代码如下:

class IInterface
{
public:
virtual void DoSomething() = 0;
}

// 不应当有析构函数, 因为从语义上说, 接口是不能delete的.

如果要delete, 只能delete一个类的实例:


代码如下:

Class A
{
Public:
Virtual ~A();

Public:
Virtual void DoSomething() = 0;
}
Class B : public A
{

}
Int main()
{
A* pA = new B();

Delete pA;
}

我们可以这样做, 因为pA对应的是一个实例, 我们可以在A这一层将其销毁.
先举个例子,方便大家理解,然后从例子中抽象概括出结理论。

比如,一家生产门的公司,需要先定义好门的模板,以便能快速生产出各种规格的门。
这里的模板通常会有两类模板:抽象类模板和接口模板。

抽象类模板:这个模板里面应该包含所有门都应该具有的共同属性(如,门的形状和颜色等)和共同行为(如,开门和关门)。

接口模板:有些门可能需要具有报警和指纹识别等功能,但这些功能又不是所有门必须具有的,所以像这样的行为应该放在单独的接口中。

有了上面的两类模板,以后生产门就很方便了:利用抽象类模板和包含了报警功能的接口模板就能生产具有报警功能的门了。同理,利用抽象类模板和包含了指纹识别功能的接口模板就能生产具有指纹识别功能的门了。

总之:抽象类用来抽象自然界一些具有相似性质和行为的对象。而接口用来抽象行为的标准和规范,用来告诉接口的实现者必要按照某种规范去完成某个功能。

这是我自己的看法,欢迎大家和我探讨这个问题。

(0)

相关推荐

  • C++类的静态成员初始化详细讲解

    记住:通常静态数据成员在类声明中声明,在包含类方法的文件中初始化.初始化时使用作用域操作符来指出静态成员所属的类.但如果静态成员是整型或是枚举型const,则可以在类声明中初始化!!! 复制代码 代码如下: #include <iostream>using namespace std;class test{public:static int num;};int test::num = 0;void main(){cout<<test::num <<endl;test::

  • c++中string类成员函数c_str()的用法

    1.string类成员函数c_str()的原型: const char *c_str()const;//返回一个以null终止的c字符串 2.c_str()函数返回一个指向正规c字符串的指针,内容和string类的本身对象是一样的,通过string类的c_str()函数能够把string对象转换成c中的字符串的样式; 3.操作c_str()函数的返回值时,只能使用c字符串的操作函数,如:strcpy()等函数.因为,string对象可能在使用后被析构函数释放掉,那么你所指向的内容就具有不确定性.

  • C++类成员构造函数和析构函数顺序示例详细讲解

    对象并不是突然建立起来的,创建对象必须时必须同时创建父类以及包含于其中的对象.C++遵循如下的创建顺序: (1)如果某个类具体基类,执行基类的默认构造函数. (2)类的非静态数据成员,按照声明的顺序创建. (3)执行该类的构造函数. 即构造类时,会先构造其父类,然后创建类成员,最后调用本身的构造函数. 下面看一个例子吧 复制代码 代码如下: class c{public:    c(){ printf("c\n"); }protected:private:}; class b {pub

  • C++中的类模板详解及示例

    C++中的函数模板 对于类的声明来说,也有同样的问题.有时,有两个或多个类,其功能是相同的,仅仅是数据类型不同,如下面语句声明了一个类: 复制代码 代码如下: class Compare_int{ public:  Compare(int a,int b)  {   x=a;   y=b;  }   int max()  {   return (x>y)?x:y;  }  int min()  {   return (x<y)?x:y;  } private:  int x,y;}; 其作用是

  • C++中的聚合类定义与用法分析

    本文实例讲述了C++中的聚合类.分享给大家供大家参考,具体如下: 聚合类是一种没有用户定义的构造函数,没有私有(private)和保护(protected)非静态数据成员,没有基类,没有虚函数.这样的类可以由封闭的大括号用逗号分隔开初始化列表.下列的代码在 C 和 C++ 具有相同的语法: struct C { int a; double b; }; struct D { int a; double b; C c; }; // initialize an object of type C wit

  • C++类静态成员与类静态成员函数详解

    当将类的某个数据成员声明为static时,该静态数据成员只能被定义一次,而且要被同类的所有对象共享.各个对象都拥有类中每一个普通数据成员的副本,但静态数据成员只有一个实例存在,与定义了多少类对象无关.静态方法就是与该类相关的,是类的一种行为,而不是与该类的实例对象相关. 静态数据成员的用途之一是统计有多少个对象实际存在. 静态数据成员不能在类中初始化,实际上类定义只是在描述对象的蓝图,在其中指定初值是不允许的.也不能在类的构造函数中初始化该成员,因为静态数据成员为类的各个对象共享,否则每次创建一

  • C++聚合关系类的构造函数的调用顺序详解

    如图,表示一个聚合关系 下面就用简单的代码来实现 #pragma once class Engine { public: Engine(); ~Engine(); }; Engine.h #include <iostream> #include "Engine.h" using namespace std; Engine::Engine() { cout << "调用构造函数:Engine()" << endl; } Engine

  • c++类构造函数详解

    复制代码 代码如下: //一. 构造函数是干什么的 /*   类对象被创建时,编译系统对象分配内存空间,并自动调用该构造函数->由构造函数完成成员的初始化工作     eg: Counter c1; 编译系统为对象c1的每个数据成员(m_value)分配内存空间,并调用构造函数Counter( )自动地初始化对象,初始化之后c1的m_value值设置为0 故:构造函数的作用:初始化对象的数据成员.*/ class Counter       {      public:       // 类Co

  • C++中抽象类和接口的区别介绍

    1. 如果一个类B在语法上继承(extend)了类A, 那么在语义上类B是一个类A.2. 如果一个类B在语法上实现了(implement)接口I, 那么类B遵从接口I制定的协议. 使用abstract class的根本原因在于, 人们希望通过这样的方式, 表现不同层次的抽象. 而interface的本质是一套协议. 在程序设计的发展中, 人们又发现接口可以用来表示对行为的抽象, 不过, 这只是interface的一种用法不是其本质. 理论结合实际才是最好的学习方式, 不过在这里, 我只想举一些我

  • Java中抽象类和接口的区别_动力节点Java学院整理

    接口 1 因为java不支持多重继承,所以有了接口,一个类只能继承一个父类,但可以实现多个接口,接口本身也可以继承多个接口. 2 接口里面的成员变量默认都是public static final类型的.必须被显示的初始化. 3 接口里面的方法默认都是public abstract类型的.隐式声明. 4 接口没有构造方法,不能被实例化. 5 接口不能实现另一个接口,但可以继承多个接口. 6 类如果实现了一个接口,那么必须实现接口里面的所有抽象方法,否则类要被定义为抽象类. 抽象类 1 如果将一个类

  • PHP中抽象类、接口的区别与选择分析

    本文实例分析了PHP中抽象类.接口的区别与选择.分享给大家供大家参考,具体如下: 区别: 1.对接口的使用是通过关键字implements.对抽象类的使用是通过关键字extends.当然接口也可以通过关键字extends继承. 2.接口中不可以声明成员变量(包括类静态变量),但是可以声明类常量.抽象类中可以声明各种类型成员变量,实现数据的封装.(另JAVA接口中的成员变量都要声明为public static final类型) <?php abstract class Father { funct

  • c#中抽象类和接口的详细介绍

    一.抽象类:抽象类是特殊的类,只是不能被实例化:除此以外,具有类的其他特性:重要的是抽象类可以包括抽象方法,这是普通类所不能的.抽象方法只能声明于抽象类中,且不包含任何实现,派生类必须覆盖它们.另外,抽象类可以派生自一个抽象类,可以覆盖基类的抽象方法也可以不覆盖,如果不覆盖,则其派生类必须覆盖它们. 二.接口:接口是引用类型的,类似于类,和抽象类的相似之处有三点: 1.不能实例化: 2.包含未实现的方法声明: 3.派生类必须实现未实现的方法,抽象类是抽象方法,接口则是所有成员(不仅是方法包括其他

  • java 抽象类与接口的区别介绍

    抽象类与接口的区别 抽象类 包含抽象方法的类就是抽象类,声明的语句:abstract class 必须是public protected 接口 对行为的抽象,声明语句:interface 抽象方法的修饰符:public abstract 成员变量的修饰符:public static final 语法层面 抽象类中可以包含成员方法的实现细节,而接口中只能存在抽象方法-public abstract 抽象类中的成员变量可以是各种类型,接口中的成员变量只能是public static final 抽象

  • C#中抽象类与接口的区别详解

    1.面向接口编程和面向对象编程是什么关系 首先,面向接口编程和面向对象编程并不是平级的,它并不是比面向对象编程更先进的一种独立的编程思想,而是附属于面向对象思想体系,属于其一部分.或者说,它是面向对象编程体系中的思想精髓之一. 2.接口的本质 接口,在表面上是由几个没有主体代码的方法定义组成的集合体,有唯一的名称,可以被类或其他接口所实现(或者也可以说继承).它在形式上可能是如下的样子: interface InterfaceName { void Method1(); void Method2

  • 详细解析Java中抽象类和接口的区别

    在Java语言中, abstract class 和interface 是支持抽象类定义的两种机制.正是由于这两种机制的存在,才赋予了Java强大的 面向对象能力.abstract class和interface之间在对于抽象类定义的支持方面具有很大的相似性,甚至可以相互替换,因此很多开发者在进 行抽象类定义时对于abstract class和interface的选择显得比较随意.其实,两者之间还是有很大的区别的,对于它们的选择甚至反映出对 于问题领域本质的理解.对于设计意图的理解是否正确.合理

  • Java详细讲解不同版本的接口语法和抽象类与接口的区别

    目录 什么是接口? 接口的语法: (JDK7.0) 接口的语法: (JDK8.0) 接口的语法: (JDK9.0)—(私有方法) 接口的分类 常量接口: 空接口: 函数式接口: 什么是接口? 说到接口,USB大家肯定不陌生~接口是一种标准.规范.注意:接口一旦制定好,使用者和实现者都必须遵循的标准. 接口的语法: (JDK7.0) (1) 关键字:interface (2) 语法:  interface 接口名{} (3) 接口编译之后会生成对应的 .class文件 (4) 接口不能创建对象,但

  • java中抽象类和接口的相同和不同点介绍

    目录 前言 一.抽象类是什么? 二.接口是什么? 三.抽象类和接口的异同点 总结 前言 本文简单介绍抽象类,接口以及它们的异同点,另附简单的代码举例. 一.抽象类是什么? 在 Java 语言中使用 abstract class 来定义抽象类.抽象类是不能被实例化的,即不能用new关键字来实例化对象.包含抽象方法的一定是抽象类,但抽象类不一定包含抽象方法.如果一个子类实现了父类(抽象类)的所有抽象方法,那么该子类可以不必是抽象类,否则就是抽象类.抽象类中的抽象方法的修饰符只能为public或者pr

  • Java中抽象类和接口介绍

    目录 1.抽象类 1.1 什么是抽象类? 1.2 抽象类属于什么类型? 1.3 抽象类怎么定义? 1.4 抽象方法 2.接口 2.1 关于接口 2.2 接口怎么定义? 2.3 接口基础语法 总结 1.抽象类 1.1 什么是抽象类? 1.1.1 对抽象类的理解 1.1.2 关于抽象类 类与类之间具有共同特征,将这些共同特征提取出来,形成的就是抽象类: 类本身是不存在的,属于抽象类无法创建对象[无法实例化]: 抽象类是用来被子类继承的: finial关键字和abstract关键字不能同时出现: 抽象

随机推荐