纯虚函数与身体的用例?

问题描述 投票:44回答:7

我最近才知道,在C ++中,纯虚函数可以选择有一个体。

这些功能的实际用例是什么?

c++ virtual-functions
7个回答
41
投票

经典是一个纯粹的虚拟析构函数:

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

abstract::~abstract() {}

你把它变成纯粹的,因为没有别的东西可以这样做,你希望这个类是抽象的,但你必须提供一个实现,因为派生类的析构函数明确地调用你的。是的,我知道,这是一本非常愚蠢的教科书例子,但同样这是一部经典之作。它一定是第一版的The C++ Programming Language

无论如何,我记不起真的需要能够实现纯虚函数。对我而言,这个功能的唯一原因似乎是因为它必须明确禁止,而Stroustrup没有看到原因。

如果您觉得自己需要这个功能,那么您的设计可能就错了。


35
投票

带或不带主体的纯虚函数只是意味着派生类型必须提供自己的实现。

如果派生类要调用基类实现,则基类中的纯虚函数体很有用。


16
投票

抽象基类(具有纯虚函数)可能为其声明的纯虚函数提供实现的一个原因是让派生类具有他们可以选择使用的简单“默认”。对于可以选择性覆盖的普通虚函数来说,这没有很多优势 - 实际上,唯一真正的区别在于你强迫派生类明确使用'默认'基类实现:

class foo {
public:
    virtual int interface();
};

int foo::interface() 
{
    printf( "default foo::interface() called\n");
    return 0;
};


class pure_foo {
public:
    virtual int interface() = 0;
};

int pure_foo::interface()
{
    printf( "default pure_foo::interface() called\n");
    return 42;
}

//------------------------------------

class foobar : public foo {
    // no need to override to get default behavior
};

class foobar2 : public pure_foo {
public:
    // need to be explicit about the override, even to get default behavior
    virtual int interface();
};

int foobar2::interface()
{
    // foobar is lazy; it'll just use pure_foo's default
    return pure_foo::interface();
}

我不确定是否有很多好处 - 也许在设计从抽象类开始的情况下,然后随着时间的推移发现很多派生的具体类都在实现相同的行为,所以他们决定改变这种行为到纯虚函数的基类实现。

我认为将普通行为放入纯虚函数的基类实现中可能也是合理的,派生类可能需要修改/增强/扩充。


8
投票

一个用例是从类的构造函数或析构函数中调用纯虚函数。


8
投票

全能的Herb Sutter,前C ++标准委员会主席,did give 3 scenarios,您可以考虑为纯虚方法提供实现。

必须亲自说 - 我发现它们都没有令人信服,并且通常认为这是C ++的语义瑕疵之一。似乎C ++不遗余力地构建和拆除抽象父级vtable,而不仅仅是在儿童建设/破坏期间短暂暴露它们,and then社区专家一致推荐never to use them


4
投票

虚拟函数与body和纯虚函数与body的唯一区别在于存在第二个阻止实例化。你不能在c ++中标记类抽象。


3
投票

在学习OOD和C ++时,这个问题确实令人困惑。就个人而言,我脑子里总会有一件事情如下:如果我需要一个Pure Virtual功能也有一个实现,那么为什么要把它作为“Pure”放在首位呢?为什么不将它只留下“虚拟”并获得好处并覆盖基础实现?

令人困惑的是,许多开发人员认为没有主体/实现是定义纯虚函数的主要目标/好处。这不是真的!在大多数情况下,缺乏身体是具有纯虚函数的逻辑结果。拥有纯虚函数的主要好处是定义合约!通过定义一个纯虚函数,你想要FORCE每个派生到ALWAYS提供他们自己的功能实现。这个“合同方面”非常重要,特别是如果您正在开发类似公共API的东西。使函数只是虚拟的不够,因为派生不再被迫提供自己的实现,因此您可能会失去合同方面(这可能是公共API的限制)。正如通常所说:“虚拟功能可以被覆盖,纯虚拟功能必须被覆盖。”在大多数情况下,契约是抽象概念,因此对于具有任何实现的相应纯虚函数没有意义。

但有时候,因为生活很奇怪,你可能想要在衍生品之间建立一个强大的契约,并希望它们以某种方式从某些默认实施中受益,同时为合约指定自己的行为。即使大多数图书作者建议避免陷入这些情况,也需要提供安全网以防止最坏情况!一个简单的虚函数是不够的,因为可能存在逃避合同的风险。因此,C ++提供的解决方案是允许纯虚函数也能够提供默认实现。

上面引用的Sutter文章给出了具有纯虚拟功能和身体的有趣用例。

© www.soinside.com 2019 - 2024. All rights reserved.