不使用纯虚函数的 C++ 接口

Posted

技术标签:

【中文标题】不使用纯虚函数的 C++ 接口【英文标题】:C++ interface without using a pure virtual function 【发布时间】:2019-08-26 10:06:40 【问题描述】:

关于c++中接口类的表达我有以下疑问;

到目前为止,我学到的是,如果我们想在 c+ 中创建接口,我们使用纯虚函数,即类似

class A_Interface 
      // pure virtual function
      virtual std::string helloWorld() = 0;
;

此问题已在 SO 中多次回答。

但是,如果我们有一个复杂的多重继承级别,比如

A : A_Interface
B : A

C : B

D : C

等等

有时我们不想在所有子类中重写完全相同的纯虚方法,因为基类实现可能就足够了。 此外,这非常困难且非常耗时,尤其是当我们处理数百个课程时。

目前我知道避免这种情况的唯一方法是使用普通的虚函数。这使我免于在所有派生类中实现“helloWorld”函数, 但也有负面影响,在这种情况下,我需要指定默认行为,否则会出现“未定义的引用”之类的错误。

class A_Interface 
      // pure virtual function
      virtual std::string helloWorld()
            return "hello from A_interface class";
        ;
;

我不确定这个解决方案是否可以,因此有以下两个问题:

1) 使用简单的虚函数而不是纯虚函数来声明接口是否被认为是不好的做法?如果可以,请详细说明为什么?

2) 有没有办法在接口类 A 的这种情况下不提供基类中的默认实现而声明一个虚函数,而是在派生类中提供至少一个(或多个实现),即在 B 中, C 和 D。

我想我的第二个问题的答案很遗憾是否定的,但只是想在继续我的代码之前确定一下。我之所以问这个问题是因为我重写了默认行为是“A”和“B”类,在这种情况下,“A_Interface”类中的“helloWorld”的主体永远不会被使用。

如果代码是使用以下 -pedantic 开关编译的,则问题是相关的,即

set(CMAKE_VERBOSE_MAKEFILE true)
set (CMAKE_CXX_STANDARD 17)
add_definitions(-std=c++17 )


if(UNIX)
    add_definitions(" -pedantic -pedantic-errors -W ")
    add_definitions(" -Wall -Werror  ")
#    add_definitions(" -g  ")
endif(UNIX)

【问题讨论】:

【参考方案1】:

1) 使用简单的虚函数而不是纯虚函数来声明接口是否被认为是不好的做法?如果可以,请详细说明为什么?

那么你没有定义一个接口,或者说你创建的不仅仅是一个接口,你也在创建一个默认行为。根据您的用例,没关系。

2) 有没有办法在接口类 A 的这种情况下不提供基类中的默认实现而声明一个虚函数,而是在派生类中提供至少一个(或多个实现),即在 B 中, C 和 D。

当然。为什么不呢? A 中的纯虚拟,B 中的实现。或者我不明白这个问题。

【讨论】:

感谢您的快速反馈。关于第二个答案,我的意思是不使用纯虚拟方法。 @Tito “没有纯虚拟方法”,这似乎是一个随机要求。为什么要施加这种限制? 好吧,事实是我只是懒惰,我不想在我在这里的所有 60 个班级中实现这一点。这就是原因 @Tito 如果所有实现都相同,您不会在所有 60 个类中实现。那是不可取的。您在基类中实现。很抱歉,我仍然没有在这里看到问题。 @Tito 这就是为什么你不把它变成纯虚拟的,而是为它提供一个实现。我觉得我们在这里绕圈子。【参考方案2】:

请记住,您可以在层次结构的任何点定义虚拟方法,并且任何派生类也将继承实现。

您有一些选择,具体取决于您想要实现的目标:

1) 将B 拆分为AbstractB : A,它不提供helloWorld() 的实现,ConcreteB : AbstractB 提供具体的实现。 现在您可以选择是否从具有默认行为的类继承。

2) 将A 接口拆分为AInterfaceHelloWorldInterface。您现在可以为HelloWorldInterface 提供任何具体的实现,并以更适合您的方式继承。

无论如何,您没有充分阐明您的用例,因此我无法更具体地提供解决方案。

【讨论】:

以上是关于不使用纯虚函数的 C++ 接口的主要内容,如果未能解决你的问题,请参考以下文章

C++ 虚函数和纯虚函数的区别

C++ 纯虚函数接口,标准 C 导出 DLL 函数的用法

C++面向对象:C++ 接口(抽象类)

C++ 纯虚函数

C++11接口纯虚析构函数

c++ 虚函数和纯虚函数