提供纯虚函数的定义
Providing a definition for a pure-virtual function
我是一名Java程序员,对提供纯虚拟函数定义的事实感到困惑。在Java中,我习惯于将抽象方法视为我们将在基类中提供定义的方法。但是以下代码是完全有效的:
#include <iostream>
struct A
{
virtual ~A() = 0;
};
A::~A(){ std::cout << "~A()" << std::endl; }
struct B : A
{
~B(){ std::cout << "~B()" << std::endl; }
};
A *a = new B;
int main()
{
delete a;
}
但是,如果我们尝试做这样的事情:
#include <iostream>
struct A
{
virtual ~A() = 0;
virtual void foo() = 0;
};
void A::foo(){ }
A::~A(){ std::cout << "~A()" << std::endl; }
struct B : A
{
~B(){ std::cout << "~B()" << std::endl; }
};
A *a = new B;
int main()
{
delete a;
}
编译器会抱怨没有为纯虚函数提供定义。为什么我们可以在同名作用域中定义纯虚拟析构函数,但不能为通常的成员函数执行此操作。
这与其说是规则,不如说是例外吗?
您可以定义任何纯虚拟成员函数。但是,即使您定义了 A::foo
,它仍然是纯的,因此 A
和 B
仍然是抽象类,可能无法实例化。这将是编译器可能发出的任何错误的原因。
您显然对代码第二版中错误的原因感到困惑。
在命名空间范围内为纯虚函数(任何纯虚函数)提供定义并没有错。无论是析构函数还是常规函数都无关紧要。没有编译器会抱怨这一点。
您在代码的第二个版本中提供的A::foo
定义是完全合法的,并且不会引起编译器的投诉。第二个代码的唯一问题是B
不会覆盖foo
。因此B
仍然是一个抽象类。您正在尝试实例化它。
在代码的第一个版本中,B
从A
继承的唯一纯函数是析构函数,析构函数的非纯定义在B
中提供。因此,B
不再是抽象类,可以合法地实例化。
在代码的第二个版本中,B
从A
继承了两个纯虚函数 - 析构函数和foo
。由于您没有在 B
中覆盖foo
,B
仍然是一个抽象类,无法实例化。
仅此而已。该错误与在命名空间范围内为纯虚函数提供主体的能力无关。
当我使用 g++ 4.8.2 编译上述程序时,我收到以下消息:
编译器命令:
g++ -Wall -std=c++11 socc.cc -o socc
错误消息:
socc.cc:17:12: error: cannot allocate an object of abstract type ‘B’
A *a = new B;
^
socc.cc:12:8: note: because the following virtual functions are pure within ‘B’:
struct B : A
^
socc.cc:9:6: note: virtual void A::foo()
void A::foo(){ }
^
make: *** [socc] Error 1
错误消息的要点是B
是一个抽象类型,因为它不提供覆盖void foo();
,在基类中声明为纯虚函数。
A::foo()
的定义并不违法。以下程序工作正常:
#include <iostream>
struct A
{
virtual ~A() = 0;
virtual void foo() = 0;
};
void A::foo(){ }
A::~A(){ std::cout << "~A()" << std::endl; }
struct B : A
{
~B(){ std::cout << "~B()" << std::endl; }
void foo() {} // Need this to be able to instantiate B.
};
A *a = new B;
int main()
{
delete a;
}
- 在命名空间中定义函数还是限定函数
- 为什么在定义函数之前先声明它
- 使用用户定义函数的字符串反转
- 用户定义函数中的指针和输入
- 这个c++代码是如何在没有定义函数的情况下运行的
- 具有外部"c"和程序集的未定义函数
- 已定义函数时出现 G++ "未定义的引用"错误
- 将自定义函数传递到基抽象类中以延迟执行
- C++使用 rand 定义函数语法
- Arduino:在 loop() 和自定义函数中运行相同的代码时出现问题
- 将具有固定签名的自定义函数名称注入 CRTP
- 使用定义函数模板别名
- 是否可以使用单个定义定义函数的常量和常规版本?(使用模板,自动,decltype等)
- 在内联程序集中定义函数和从 C++ 调用时出现问题
- 在 Metal 着色器代码中,如何定义函数的 in/out 参数变量?
- 声明和定义函数静态会产生"undefined reference to function_name()"
- 朋友定义函数的名称空间是什么
- 介子 对用户定义函数的未定义引用
- 如何使用 "using" 关键字定义函数原型/签名
- 在 C 结构中定义C++函数