派生纯虚函数的实现
Deriving implementation of pure virtual function
考虑以下示例
#include <iostream>
struct PureVirtual {
virtual void Function() = 0;
};
struct FunctionImpl {
virtual void Function() {
std::cout << "FunctionImpl::Function()" << std::endl;
}
};
struct NonPureVirtual : public FunctionImpl, public PureVirtual {
using FunctionImpl::Function;
};
int main() {
NonPureVirtual c;
c.Function();
}
编译器(GCC 4.9,Clang 3.5(退出并显示错误
test.cpp:18:20: error: variable type 'NonPureVirtual' is an abstract class
NonPureVirtual c;
^
test.cpp:4:18: note: unimplemented pure virtual method 'Function' in 'NonPureVirtual'
virtual void Function() = 0;
^
但是当我不得出形式PureVirtual
一切都很好。这很奇怪,因为标准 10.4.4 说
如果一个类包含或继承至少一个纯最终覆盖器为纯虚拟的虚函数。
他们没有说最终覆盖器是什么,但我想它应该是FunctionImpl::Function()
特别是当我通过using
指令提供它时。那么为什么仍然是抽象类NonPureVirtual
我该如何解决这个问题。
FunctionImpl::Function
和PureVirtual::Function
是来自不同类的不同函数。
它们各自的类型是 void (FunctionImpl::*)()
和 void (PureVirtual::*)()
.
由于PureVirtual
和FunctionImpl
是不相关的类,因此这些函数类型是不相关的。
碰巧具有相同的名称、相同的参数和返回类型,但由于它们不同,因此using FunctionImpl::Function
行不会使该函数覆盖 PureVirtual
中的函数。
如果你声明了一个类型 void (PureVirtual::*)()
的变量,你将无法FunctionImpl::Function
赋给它。
换句话说,PureVirtual::Function
的最终覆盖是PureVirtual
中的原始覆盖,它是纯虚拟的。
为了让你想要的东西成为可能,Matthieu M.的答案(使用转接电话(似乎是要走的路。
您不能使用 using
指令,而必须求助于调用:
struct NonPureVirtual : public FunctionImpl, public PureVirtual {
virtual void Function() override {
return FunctionImpl::Function();
}
};
是的,它按预期工作。
你用它不做的事情来归因于一个 using 声明。它的作用是(来自草案 n3337,7.3.3/1(:
。使用声明将名称引入到出现使用声明的声明性区域中。
后来来自同一段:
如果 using 声明命名构造函数 (3.4.3.1(,它将隐式声明一组构造函数 出现使用声明的类 (12.9(;否则,在 using-声明中指定的名称为 在其他地方声明的某个实体的名称的同义词。
在您的情况下,FunctionImpl::Function
首先在类中声明FunctionImpl
并且它是其成员。使用声明不会改变这一事实,正如第16段所说:
出于重载解析的目的,由 using-声明引入派生类的函数将被视为派生类的成员。特别是,应将隐式
this
参数视为指向派生类而不是基类的指针。 这对函数的类型没有影响,并且在所有其他方面,函数仍然是 基类。
现在来看覆盖的定义 (10.3/2(:
如果一个虚成员函数
vf
在类Base
和类Derived
中声明,直接或间接派生自Base
,一个成员函数vf
与声明Base::vf
具有相同的名称、参数类型列表(8.3.5(、cv-限定符和ref限定符(或没有相同(,那么Derived::vf
也是虚拟的(无论它是否如此声明(,它覆盖Base::vf
。为了方便起见,我们说任何虚拟函数都会覆盖自身。
在同一段中还有最终覆盖器的定义。
类对象的虚拟成员函数
C::vf
S
是最终覆盖器,除非派生最多的类 (1.8((其中S
是基类子对象(如果有(声明或继承另一个重写vf
的成员函数。在派生类中,如果基类子对象的虚拟成员函数具有多个最终重写程序,则程序格式不正确。[...]
我认为这清楚地表明您不能使用 using 声明来覆盖虚函数。一个可能的解决办法是在马修的回答中。
- 在命名空间内部还是外部实现 c++ 函数?
- 如何在C++中实现函数(f)(x)(y, z)(g)(r)
- 如何在C++中实现函数上的二叉搜索?
- 键按下事件错误 Qt 实现函数时
- 在子类之外实现函数导致未知错误
- 通过模板滥用实现函数式C++
- C++,实现函数"int next(std::string param)"时出现奇怪的编译器错误
- 我正在尝试创建自己的 strcat() 函数,而不是使用库实现函数<cstring>
- 如果未实现函数,则在链接时启用错误
- 用函数参数实现c++函数指针
- 如何在Android SDK中调用和实现C++函数
- 在 C++ RCPP 中实现 R 函数
- 实现函数模板填充多维对象
- 类的层次结构,试图在基本级别实现函数
- 用c++实现函数对象的自动检测类型
- 用shared_ptrs实现函数模板的C++实例化
- 在类中实现函数导致错误:成员引用基类型'ifstream (string)'不是结构或联合
- 用c++实现S函数.生成错误
- 引用可以用于实现函数重写吗
- 如何在c++中实现函数超时