【问题标题】:Interfaces, absolutly nothing other then pure virtual functions, or...?接口,绝对是纯虚函数,或者......?
【发布时间】:2012-08-08 16:30:23
【问题描述】:

每次我读到接口时,都会提到它没有任何数据成员或实现。

但是当我看到带有接口的代码时,它们都有。

class IInterface
{
public:
    IInterface(){}
    virtual ~IInterface(){}
    int getInt(){ return m_int; }
    virtual void Boo() = 0;
    int m_int;
};

class cInterface : public IInterface
{
public:
    virtual void    Boo()
                    {
                        printf( "defined in .cpp for readability\n" );
                    };
};

class cFoo : public cInterface
{
};

(几乎)我从来没有在源文件中看到它们,只有标题。

术语的使用有多严格,如果上面不是接口,它是如何调用的?

cInterface/cFoo作为IInterface*使用时是否反映了它的用法?

...
cFoo foo;
IInterface* object = &foo;
object->Boo();
...

【问题讨论】:

    标签: c++ inheritance interface terminology


    【解决方案1】:

    C++ 在其语言定义中没有接口类型的正式定义,也没有办法强制编写纯抽象类。然而,这个概念肯定存在于软件工程中,并且可以追溯到很长很长的路要走。 Corba 和 COM 是典型的例子。通用技术称为“基于接口的编程”。另一个流行的标签是“按合同设计”。一些 C++ 编译器具有支持它们的语言扩展,例如 MSVC 中的 __interface。它在其他方面仍然是一个普通的类,编译器只是强制执行纯度。

    一个具体的例子是使用一个接口来定义一个实际存在于另一个运行时环境中的对象的代理。就像在地球另一端的机器上一样。代理,接口的本地实现,具有在线路上发送参数值的方法。电线的另一端有一个带有实际方法的存根。如果对象实际上是在本地创建的,客户端代码将不需要任何更改,其主要优点是它仍然使用相同的接口。换句话说,实现是不可见的,不会影响代码。您提供的示例将在这种情况下正确运行,远程对象将不会具有 m_int 成员的正确值。它不是一个接口,只是一个抽象类。

    接口在不实现多重继承的语言中尤为重要。由于钻石问题,MI 很困难。但这是一个实现继承问题,继承多个接口没有问题。这种语言必须解决的唯一小问题是当两个或多个继承接口具有具有相同名称和签名的方法时的歧义。但这可以通过为语言提供一种方法来指定正在实现的特定接口方法来轻松解决。就像 C# 中的“显式接口实现”语法一样。不确定Java是做什么的。

    另一个既实用又麻烦的方面是它是设计工具,即“按合同设计”的角度。如果你和很多开发人员一起做一个大型项目,那么你最终会得到很多接口。它们结合了建筑师发出的“这是我们应该做的”。但是没有任何“这就是我所做的”,尤其是在项目的早期。真正的错误是实现错误,很少是接口错误。一个真正让多个程序员同时工作的优秀工具。但主要是让项目的基础健全并锁定,这样你就可以在上面进行构建。不是 Bjarne 的工作方式。

    【讨论】:

    • 接受了额外的 MI、可怕的钻石和我最近几天研究了一下的合同设计。
    【解决方案2】:

    C++ 中对这个术语没有严格的定义。它通常松散地用来表示一个主要是抽象的类:一个定义交互协议而不是任何类型的实现的类。由于它不是语言中构建的概念,因此人们可以对定义不那么严格,数据有时会潜入“接口”。

    然而,在某些编程语言和系统中——Java 就是一个典型的例子——它是一种语言特性,并且具有非常正式的含义。在这些环境中,确切的含义当然是特定于环境的,但通常与上面讨论的大致相同。在 Java 中,interface 是一种只有纯虚函数和编译时常量数据成员的类。 Java 允许一个类扩展另一个类,但一个类可以实现任意数量的接口。

    【讨论】:

    • Java 经常被提及。你知道这个术语是从 Java 中采用的吗?
    • @JohnSmith 这个概念在java之前就已经存在了,但是在java中它是形式化的并且有一个关键字。
    【解决方案3】:

    简单地说,“接口”可以用来指代方法和/或数据——具体的或抽象的(例如virtual)。 “接口”的更基本定义也经常用于指代您的实现可以访问的内容(例如,公共方法是公共接口的一部分)。

    正如 Ernest 所指出的,您似乎在某些时候所期望的定义是 Java 的定义,而 Java 的定义则大不相同,因为它意味着非常具体的东西。 Java对接口的表示/定义类似于C++中的纯抽象类。

    所以,“接口”不等同于 C++ 中的纯抽象类——它是一个更通用的术语,可以用来指代对象的 声明 方法(虚拟与否)和基类(但不包括这些方法的定义)。我说,即使声明的 typedef 和常量也可以作为对象接口的一部分(特别是在模板元编程中);尽管我怀疑某些人的定义可能太过分了(实际上,接口在 C++ 中并没有严格定义——所以一个人的定义可能会因他们经常光顾的水坑而异)。

    【讨论】:

    • 不,接口不能引用抽象数据。这将需要一场重大的硬件革命或破解语言标准。它不是完全陌生的,其他语言支持属性。实际上是方法,getter 和 setter。不是 C++ 特性,它是一个相当有漏洞的抽象。
    • @HansPassant 你显然在想一些与我不同的东西——也许我们应该先解释一下你如何认为“具体数据”是可以接受的,而“抽象数据”是令人反感的。上下文:这个问题被标记为 C++ - 没有其他语言。
    猜你喜欢
    • 1970-01-01
    • 2016-10-13
    • 1970-01-01
    • 2011-03-03
    • 1970-01-01
    • 2022-01-13
    • 1970-01-01
    • 2014-12-15
    • 2013-10-04
    相关资源
    最近更新 更多