C++ 纯虚函数及其实现

C++ 纯虚函数及其实现,c++,pure-virtual,C++,Pure Virtual,我的基本理解是,没有纯虚拟函数的实现,但是,有人告诉我可能有纯虚拟函数的实现 class A { public: virtual void f() = 0; }; void A::f() { cout<<"Test"<<endl; } A类{ 公众: 虚空f()=0; }; void A::f(){ cout如果您有应该由派生类执行的代码,但是您不希望直接执行它,并且希望强制重写它 您的代码是正确的,尽管总的来说,这不是一个经常使用的功能,并且通常只在

我的基本理解是,没有纯虚拟函数的实现,但是,有人告诉我可能有纯虚拟函数的实现

class A {
public:
    virtual void f() = 0;
};

void A::f() {
    cout<<"Test"<<endl;
}
A类{
公众:
虚空f()=0;
};
void A::f(){

cout如果您有应该由派生类执行的代码,但是您不希望直接执行它,并且希望强制重写它

您的代码是正确的,尽管总的来说,这不是一个经常使用的功能,并且通常只在尝试定义纯虚拟析构函数时才出现——在这种情况下,您必须提供一个实现。有趣的是,一旦您从该类派生,就不需要重写析构函数

因此,纯虚函数的一个合理用法是将纯虚析构函数指定为“non-final”关键字

以下代码非常正确:

class Base {
public:
  virtual ~Base() = 0;
};

Base::~Base() {}

class Derived : public Base {};

int main() { 
  // Base b; -- compile error
  Derived d; 
}

它的优点是,它强制派生类型仍然重写该方法,但也提供了默认或附加实现。

虚拟
函数必须在将直接实例化的派生类型中实现,但是基类型仍然可以定义实现。派生类可以显式地所有基类实现(如果访问权限允许)都是通过使用全范围名称(在您的示例中,通过调用
a::f()
——如果
a::f()
)实现的。类似于:

class B : public A {

    virtual void f() {
        // class B doesn't have anything special to do for f()
        //  so we'll call A's

        // note that A's declaration of f() would have to be public 
        //  or protected to avoid a compile time problem

        A::f();
    }

};
我脑海中能想到的用例是,存在或多或少合理的默认行为,但类设计器希望仅显式调用此类默认行为。也可能是您希望派生类始终执行其自己的工作,但也能够调用公共功能集的情况


注意,即使语言允许,它也不是我经常看到的(而且它可以做到的事实,似乎让大多数C++程序员感到惊讶,甚至是有经验的程序员)。但您强制派生类实现方法f()(即使只是调用由提供的默认实现)


Scott Meyers在有效C++(第二版)中讨论了这一点:36区分接口的继承和实现的继承。在最新版本中,项目号可能已经改变。

< P>要清楚,你误解了什么=0;在虚函数之后。

=0表示派生类必须提供实现,而不是基类不能提供实现。


实际上,当您将虚拟函数标记为纯(=0)时,提供定义几乎没有意义,因为除非有人通过Base::function(…)显式调用它,否则它永远不会被调用或者如果基类构造函数调用有问题的虚函数。

您必须给纯虚析构函数一个主体,例如:)

阅读:


纯虚拟函数(带或不带主体)仅仅意味着派生类型必须提供自己的实现

如果派生类希望调用基类实现,基类中的纯虚函数体非常有用。

虚空foo()=0;'语法并不意味着不能在当前类中实现foo(),可以。它也不意味着必须在派生类中实现它。。 在你扇我耳光之前,让我们先看看钻石问题: (请注意,隐式代码)

现在,obj->foo()调用将产生B::foo(),然后是C::bar()

您知道……纯虚拟方法不必在派生类中实现(foo()在类C中没有实现-编译器将编译) 在C++中有很多漏洞。
希望我能提供帮助:-)

拥有一个带有实现体的纯虚拟方法的一个重要用例是,当您想要一个抽象类,但该类中没有任何适当的方法使其纯虚拟。在这种情况下,您可以使该类的析构函数纯虚拟,并将所需的实现这是一个很好的解释(甚至是一个空的身体)。例如:

class Foo
{
   virtual ~Foo() = 0;
   void bar1() {}
   void bar2(int x) {}
   // other methods
};

Foo::~Foo()
{
}

此技术使
Foo
类抽象,因此无法直接实例化该类。同时,您没有添加额外的纯虚拟方法来使
Foo
类抽象。

基类析构函数始终被调用,无论是虚是非,还是纯是非;使用其他函数,您可以无论基类版本是否为纯版本,都不能保证重写虚拟函数将调用基类实现。该代码是错误的。由于该语言的语法问题,您必须在类定义之外定义dtor。@罗杰:谢谢,这确实帮助了我——这是我一直在使用的代码,它编译得很好nder MSVC,但我想它不会是可移植的。这是不正确的。如果在纯虚拟类的构造函数中调用纯虚拟函数,将进行纯虚拟调用。在这种情况下,最好有一个实现。@rmn,是的,关于构造函数中的虚拟调用,你是对的。我更新了答案。希望每个人都不知道但是,要做到这一点::)事实上,从构造函数进行基本纯调用会导致实现定义的行为。在VC++中,这相当于一个_purecall崩溃。@OfekShilon这是正确的-我可能也会将其称为未定义的行为,并可能导致错误的实践/代码重构(即在构造函数内调用虚拟方法)。我想这与虚拟表的一致性有关,它可能不准备路由到正确实现的主体。在构造函数和析构函数中,虚拟函数不是虚拟的。您可以
class Foo
{
   virtual ~Foo() = 0;
   void bar1() {}
   void bar2(int x) {}
   // other methods
};

Foo::~Foo()
{
}