每次我阅读有关接口的内容时,都会提到它没有任何数据成员或实现。
但是当我看到带有接口的代码时,它们都有。
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
{
};
(差不多)我从未在源文件中看到它们,只看到了标题。
使用的术语有多严格,如果以上不是界面,它是如何调用的?
当它用作IInterface *时,它是否反映了cInterface / cFoo的用法?
...
cFoo foo;
IInterface* object = &foo;
object->Boo();
...
答案 0 :(得分:6)
C ++在其语言定义中没有正式的接口类型定义,也无法强制编写纯抽象类。然而,这个概念肯定存在于软件工程中,并且可以追溯到很长很长的路要走。 Corba和COM是典型的例子。通用技术称为“基于接口的编程”。另一个受欢迎的标签是“按合同设计”。一些C ++编译器具有支持它们的语言扩展,如MSVC中的__interface。它仍然是一个普通的类,编译器只是强制执行纯度。
一个具体示例是使用接口作为实际位于另一个运行时环境中的对象的代理定义。就像在世界各地的机器上一样。代理(接口的本地实现)具有在线路上发送参数值的方法。电线的另一端有一个实际方法的存根。如果对象实际上是在本地创建的,那么客户端代码无需任何更改即具有主要优势,它仍然使用相同的接口。换句话说,实现是不可见的,不会影响代码。您提供的示例 not 在此方案中无法正常运行,远程对象将没有m_int成员的正确值。它不是一个接口,只是一个抽象类。
接口在不实现多重继承的语言中尤为重要。由于钻石问题,MI很难。但这是实现继承问题,继承多个接口没有问题。当两个或多个继承的接口具有相同名称和签名的方法时,这种语言必须解决的唯一小问题是模糊性。但是,通过为语言提供指定正在实现哪种特定接口方法的方法,可以轻松解决这个问题。就像C#中的“显式接口实现”语法一样。不确定Java是做什么的。
另一个既实用又麻烦的方面是它是设计工具,即“按合同设计”的角度。如果您与大量开发人员一起开展大型项目,那么您往往会遇到很多接口。它们包含了“这是我们应该做什么”,由建筑师发出。但没有任何“这就是我所做的”,特别是在项目的早期。真正的错误是实现错误,很少是接口错误。实际上让多个程序员同时工作的一个很好的工具。但主要是为了获得项目声音的基础并锁定,以便您可以建立在顶部。不是Bjarne的工作方式。
答案 1 :(得分:2)
在C ++中没有严格的术语定义。它通常使用松散来表示一个主要是抽象的类:一个定义交互协议的类,而不是任何类型的实现。由于它不是一个用语言构建的概念,人们可能对定义不那么严格,数据有时会潜入“界面”。
在某些编程语言和系统中,Java是一个主要的例子 - 它是一种语言特性,具有非常正式的含义。在这些环境中,精确的含义当然是特定于环境的,但通常与上面讨论的大致相同。在Java中,接口是一种只有纯虚函数和编译时常量数据成员的类。 Java允许类扩展只是另一个类,但是一个类可以实现任意数量的接口。
答案 2 :(得分:0)
简单地说,'interface'可以用来指代方法和/或数据 - 具体或抽象(例如virtual
)。 “接口”的更基本定义也经常用于指代您的实现可以访问的内容(例如,公共方法是公共接口的一部分)。
所以,'interface'不等同于C ++中的纯抽象类 - 它是一个更通用的术语,可用于引用对象的声明的方法(虚拟)或不)和基类(排除这些方法的定义)。我说,即使声明typedef和常量也可以作为对象界面的一部分(特别是在模板元编程中);虽然我怀疑某些人的定义可能太过分了(实际上,在C ++中没有严格定义界面 - 所以一个人的定义可能因他们经常光顾的水坑而有所不同。)