C++ 应该是C++;纯虚拟类需要定义吗?

C++ 应该是C++;纯虚拟类需要定义吗?,c++,class,C++,Class,考虑: // in header.h class A { public: virtual ~A() = 0; }; class B : public A { public: ~B() override {} } 链接器报告它无法解析: 函数“public:virtual\uu thiscall B::~B(void)”中引用的外部符号“public:virtual\uu thiscall A::~A(void)” 我发现我必须编写A::~A()的定义 我过去认为纯虚拟类定义

考虑:

// in header.h
class A {
public:
    virtual ~A() = 0;
};


class B : public A {
public:
    ~B() override {}
}
链接器报告它无法解析:

函数“public:virtual\uu thiscall B::~B(void)”中引用的外部符号“public:virtual\uu thiscall A::~A(void)”

我发现我必须编写
A::~A()
的定义


我过去认为纯虚拟类定义接口(函数声明),它们不必包含函数定义。我应该为纯虚拟基类中的所有虚拟函数编写定义吗?还是只需要编写析构函数?

这是因为与常规虚拟函数不同,析构函数不仅仅被重写。在基类上调用常规虚函数时,最终只调用重写该函数的函数

但是,对于析构函数,还必须调用基类的析构函数。但是,由于您没有提供
~A()
的实现,因此您的代码无法链接


但是您可以定义函数,即使它是纯虚函数:。

要使类抽象,您需要至少使一个虚函数为纯函数。若你们并没有其他的解构函数,那个么析构函数就是一个很好的选择。但另一方面,析构函数是一个特例——你们必须定义它,即使它是纯的

注意:您也可以定义常规纯虚拟函数,例如拦截错误条件(类似于从ctor或dtor调用纯函数),但与析构函数不同的是,不提供此类定义是可以的,编译器将在那里生成错误处理程序,它将报告调用的纯虚拟函数

是否应该使用C++ <强>纯虚拟类< /St>需要定义?< /P> 第一个错误是你为自己发明了术语。没有所谓的“纯虚拟类”。只有“虚拟功能”和“纯虚拟功能”。理解不存在“纯虚拟类”是理解为什么这个问题不成立的关键

我曾经认为纯虚拟类定义了一个接口(函数声明)

我认为C++不是你的第一语言,而是java/C++之后的第二语言,你认为爪哇和C的想法与C++无关。 C++有接口-它只是类的声明:

struct A{

    void doNothing();

};

//A.cpp:
void A::doNothing(){

}
这是struct A的接口。它是否与继承、虚拟函数或多态性有关?不,它只是类的声明,其中存在什么方法和属性

每个类都需要一个有效的析构函数来允许程序清理对象资源——内存等。它与多态性无关。在您的示例中,
A
需要以某种方式进行销毁。
B
继承它并不重要。它必须告诉程序在超出范围时如何处理它

如注释中所述,如果您只需要一个虚拟析构函数(因此在
a*a=new B()
的情况下不会显示UB),只需将析构函数声明为默认值:

virtual ~A() = default;

作为对我前辈的补充,你可以读到它

可以提供纯虚函数的定义(,如果纯虚函数是析构函数,则必须提供该定义)):派生类的成员函数可以使用限定函数id自由调用抽象基的纯虚函数。该定义必须在类体之外提供(函数声明的语法不允许纯说明符=0和函数体)


你可以只使用virtual~A()=default;@linuxfever啊,但是它不是纯的,不是吗?
A::~A()=default;
在类范围之外。析构函数当然需要一个定义。
~B()
应该调用
~A()
作为其执行的一部分。如果
~A()
没有定义?是的,必须定义纯虚拟析构函数(在类之外),析构函数在这方面非常特殊。“析构函数不能是纯虚拟的。”直到这句话之前一切都很好。实际上,析构函数可以是纯虚拟的,并且也有一个定义:
virtual~a()=0{}
纯虚函数通常可以有定义。拥有纯虚析构函数是在没有其他纯虚方法的情况下使类抽象的唯一方法。常用的技术。所以我为“不应该”而争论子句!“OvNes”,语法是否有效?难道不应该被定义为离线吗?C++中的java接口等价物是一个纯虚拟函数类,而你的结构A {…}我认为,人们可以从C++或C++ java等语言中尽早地了解C++,一个抽象类是一个或多个纯虚函数,类接口只是外部实体可见的类定义的一部分。(即,
public
部分),而Java
接口
s只是一种很难搞糟的多重继承的框架形式。尽管使用Java 8默认方法,
接口
多重继承现在更容易搞糟。