C++中抽象类与接口的接口

Abstract Class vs Interface in C++

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
How do you declare an interface in C++?

这是一个关于C++的一般性问题。正如你所知道的,在C++中,EDCOX1和0的EDCX1和1之间没有明显的区别。在C++中,使用EDCOX1 0Ω代替EDCOX1?1是什么时候更可取?你能举几个例子吗?


我假设接口是指一个C++类,它只有纯的虚拟方法(即没有任何代码),而不是抽象类,你指的是一个C++类,它可以被重写的虚拟方法和一些代码,但是至少有一个纯虚拟方法使得类不可实例化。例如。:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class MyInterface
{
public:
  // Empty virtual destructor for proper cleanup
  virtual ~MyInterface() {}

  virtual void Method1() = 0;
  virtual void Method2() = 0;
};


class MyAbstractClass
{
public:
  virtual ~MyAbstractClass();

  virtual void Method1();
  virtual void Method2();
  void Method3();

  virtual void Method4() = 0; // make MyAbstractClass not instantiable
};

在Windows编程中,接口是COM的基础。实际上,COM组件只导出接口(即指向v表的指针,即指向函数指针集的指针)。这有助于定义一个ABI(应用程序二进制接口),使它可以在C++中构建COM组件并在Visual Basic中使用它,或者在C中构建COM组件并在C++中使用它,或者用VisualC++版本X构建COM组件并使用VisualC++版本Y来使用它。换句话说,通过接口,您可以在客户机代码和服务器代码之间实现高度的解耦。

此外,当您想用C++面向对象接口(而不是纯C DLL)构建DLL时,如本文所述,最好是导出接口("成熟的方法")而不是C++类(这基本上是COM所做的,但没有COM基础设施的负担)。

如果我想定义一组规则,使用这些规则可以对组件进行编程,而不指定具体的特定行为,那么我将使用一个接口。实现此接口的类本身将提供一些具体的行为。

相反,当我想提供一些默认的基础结构代码和行为时,我会使用一个抽象类,并使客户机代码可以从此抽象类派生,用一些自定义代码覆盖纯虚拟方法,并用自定义代码完成此行为。以OpenGL应用程序的基础架构为例。您可以定义一个抽象类来初始化OpenGL、设置窗口环境等,然后您可以从此类派生并实现自定义代码,例如渲染过程和处理用户输入:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
// Abstract class for an OpenGL app.
// Creates rendering window, initializes OpenGL;
// client code must derive from it
// and implement rendering and user input.
class OpenGLApp
{
public:
  OpenGLApp();
  virtual ~OpenGLApp();
  ...

  // Run the app    
  void Run();


  // <---- This behavior must be implemented by the client ---->

  // Rendering
  virtual void Render() = 0;

  // Handle user input
  // (returns false to quit, true to continue looping)
  virtual bool HandleInput() = 0;

  // <--------------------------------------------------------->


private:
  //
  // Some infrastructure code
  //
  ...
  void CreateRenderingWindow();
  void CreateOpenGLContext();
  void SwapBuffers();
};


class MyOpenGLDemo : public OpenGLApp
{
public:
  MyOpenGLDemo();
  virtual ~MyOpenGLDemo();

  // Rendering
  virtual void Render();  // implements rendering code

  // Handle user input
  virtual bool HandleInput(); // implements user input handling


  //  ... some other stuff
};


EDCOX1,0,主要是由Java流行的。以下是interface及其C++等价物的性质:

  • EDCOX1〔0〕可以只包含无体抽象方法;C++等价物是纯EDCOX1,3种方法,尽管它们可以/不能拥有身体。
  • EDCOX1(0)只能包含EDCOX1,5个数据成员;C++等效的是static const数据成员,它们是编译时间常量
  • 多个interface可以由class〕EDCX1×8〕,这是需要一个工具,因为Java EDCOX1(9)只能继承1个EDCOX1〔9〕;C++在EDCOX1·3的帮助下直接支持多重继承。需要时使用关键字
  • 由于点3 EDOCX1,0的概念在C++中从未正式引入。不过,这样做还是有灵活性的。

    除此之外,您还可以参考bjarne关于此主题的常见问题解答。


    当需要一些公共实现时,将使用抽象类。如果您只想指定一个契约,那么接口应该是程序的各个部分也必须遵守的契约。通过实现接口,您可以保证实现某些方法。通过扩展抽象类,您将继承它的一些实现。因此,接口只是一个抽象类,没有实现任何方法(所有方法都是纯虚拟的)。


    纯虚拟函数主要用于定义:

    a)抽象类

    这些是必须从中派生并实现纯虚拟函数的基类。

    b)界面

    这些是"空"类,其中所有函数都是纯虚拟的,因此您必须派生并实现所有函数。

    纯虚函数实际上是在基类中没有实现的函数,必须在派生类中实现。


    请不要将成员放入接口;尽管它的措辞是正确的。请不要"删除"接口。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    class IInterface()
    {
       Public:
       Virtual ~IInterface(){};
       …
    }

    Class ClassImpl : public IInterface
    {
        …
    }

    Int main()
    {

      IInterface* pInterface = new ClassImpl();
      …
      delete pInterface; // Wrong in OO Programming, correct in C++.
    }