【问题标题】:What is the difference between Abstract and interface in C++ context?C ++上下文中的抽象和接口有什么区别?
【发布时间】:2014-12-30 03:22:30
【问题描述】:

C++ 中的接口被实现为抽象类,即纯虚方法。 同样,C++ 中的抽象类也以相同的方式实现。我可以说接口和抽象在 C++ 中是相同的,除了接口可能是动词的概念 - 行为和抽象类是名词。我的理解对吗?我问这个问题是因为设计模式 - 以不同的方式谈论接口和抽象。另外,原因是 JAVA 有两个不同的关键字——接口和抽象。我们需要在java中实现一个接口。我们需要扩展抽象类。但是,在 CPP 中,我们只是从抽象类继承然后实现。

【问题讨论】:

标签: c++ design-patterns


【解决方案1】:

不,抽象类可以为方法提供默认行为;接口是纯虚拟的,不能。这是根本不同的。

行为和抽象类是名词

这毫无意义。行为总是动词。

抽象类和接口的重点是多态性:不同的行为取决于运行时类型。

【讨论】:

    【解决方案2】:

    如果它的所有方法都是抽象的,并且没有数据成员,那么 C++ 类确实是接口。但是,如果一个类至少有一个抽象方法,那么它就已经是抽象的了。仍然可以定义其他虚函数、非虚函数和数据成员。这些都不属于接口。

    【讨论】:

      【解决方案3】:

      Java 对interface 类有特定语法的原因(或原因)是因为 Java 不支持(非接口类的)多重继承。

      另一方面,C++ 确实支持多重继承,因此不需要在语言级别定义接口类。

      如果类至少有一个纯虚成员函数,则在 C++ 中类是抽象的。在 OO 设计中,没有方法实现的类称为接口。因此考虑到这个观点,虽然语言中没有特殊的语法,但 c++ 中的接口只是一个抽象类,没有非纯虚拟的成员函数,即所有成员函数都是纯虚拟的。所以,接口类是抽象类的一个子集,而不是你提议的同一个东西。

      当然,interface这个词不仅仅在接口类的上下文中具有更多的含义。例如,您通常会认为库的接口是该库的头文件中定义的所有内容。这包括所有类定义、函数、全局变量及其文档。

      【讨论】:

        【解决方案4】:

        您面临的问题主要是由于“经典 OOP 术语”是独立于 C++ 语言开发的,而这又不是纯 OOP 语言。

        尽管如此,在许多编程课程中,有一种历史趋势是通过 OOP 教授 C++,从而迫使 OOP 范式进入 C++,即使 C++ 范式更广泛。

        在纯 OOP 术语中,“接口”的意思是“描述外部行为”(与“实现”相反),而“抽象”的意思是“在更高层次上描述某事”(与“具体”相反)

        像 Java 这样的语言,其中 OOP 替换是通过专为该目的而设计的继承实现的,“接口”是“抽象的”,而类是“越来越具体”的对象层次结构。

        C++ 继承是不同的:它具有 - 在它的基础上 - 与 OOP 替换和 java 继承无关,不需要方法是虚拟的,并且可以是多个。在通用范式意义上,它只是一种聚合机制,该语言可用于将事物组合在一起。

        您可以用它来描述的问题比 OOP 本身解决的问题更广泛,同时也不能涵盖所有 Java 问题。但如果你强迫自己遵守一定的纪律,你仍然可以适应它们。

        因此:

        • 一个具有所有纯虚方法 (virtual method(params)=0) 和一个虚 dcestructor 的类,从 OOP 的角度来看类似于一个接口
        • 一个实现了所有虚拟继承方法的类就像一个实现。

        但 C++ 也承认所有中间情况(仅实现 一些 方法)并且承认实现的起源不仅来自继承祖先树的相同路径。

        事实上,C++ 承认完整的“多重继承方案”,而 java 承认“部分多重继承”,只有一个类和许多接口(也就是说所有实现的方法必须来自树的同一侧)

        您可以强制 C++ 遵守与 java 相同的规则,方法是承认(在这一点上人为地)只有继承的基类可以提供方法,而所有其他基类只能声明它们,并首先调用“类”和“接口”其他。

        但从语言的角度来看,它们之间没有概念上的区别。

        【讨论】:

          【解决方案5】:

          如您所说,C++ 中的接口是使用具有仅纯虚函数的抽象类实现的。纯虚函数必须被任何具体(即非抽象)派生类覆盖。通过向虚函数添加表达式=0,我们表明虚函数是纯虚函数。抽象类是包含至少一个纯虚函数的类。

          例如:

          class AbstractBase {
              public:
                const char* Hello() { return "Hello World!"; } // a normal non-virtual function    
          
                virtual void Method_1() {} // a normal virtual function
          
                virtual int Method_2() = 0; // a pure virtual function makes AbstractBase class not instantiable
            };  
          
          class InterfaceBase {
              public:
                const char* Hello() = 0; // a pure virtual function    
          
                virtual void Method_1() = 0; // a pure virtual function
          
                virtual int Method_2() = 0; // a pure virtual function 
            };
          

          【讨论】:

            【解决方案6】:

            这样考虑:有两种类型的函数

            1. Concrete - 有一些代码并实际执行一项任务。
            2. Virtual - 没有任何代码并且根据该类的本地需要被其他一些具体类覆盖。通过在其声明中放置“= 0”来指定虚函数。

            现在,interface 是一个空壳,其中所有函数都必须是虚函数。它只是一种模式。它旨在由程序员通过覆盖其虚函数来完全修改。

            但是,abstract class 是一个仅由程序员部分实现的类。也就是说,它必须至少有一个虚函数,但不一定全部。

            【讨论】:

              猜你喜欢
              • 2010-12-27
              • 2018-10-11
              • 2010-12-12
              • 2019-12-14
              • 2010-11-13
              • 2013-02-17
              • 2011-04-04
              相关资源
              最近更新 更多