【问题标题】:use of pure virtual function defined outside the class in C++?使用在 C++ 类之外定义的纯虚函数?
【发布时间】:2014-09-08 19:21:48
【问题描述】:

我在网上看到,我们很少会定义函数,即使它在下面的类中定义为纯虚拟。

class abc
{
    public:
        virtual void func() = 0;
}

void abc::func()
{
    cout << "in abc::func()";
}

我不明白这个的用途。在链接http://www.gotw.ca/gotw/031.htm 上,提到我们可以将其用作纯虚拟析构函数。但是我还没有清楚的理解。谁能告诉我有什么用途。

【问题讨论】:

  • 答案在链接中:如果您想阻止其他人实例化您的类,这很有用。就个人而言,我认为有更好的方法可以做到这一点(例如,将构造函数声明为private)。
  • @barak manos:确实,虽然一个简单的“#define private public”会打破这一点
  • @StealthyHunter7 是的,“simpel”行会破坏您的标准合规性(很可能是您的整个项目
  • @StealthyHunter7:哈哈,你可以在这里将它作为一个单独的问题发布......诸如“为什么(在地球上)有人想要#define private public?”或“@987654325 能做什么? @可能有好处吗?” (答案可能是“什么都没有!”+ 对你的问题投了几票)。
  • @barak manos:实际上有这样一个案例,有人在做项目时使用它,而构建 API 的团队还没有完成,所以他们没有使用接口,而是直接使用私有成员.

标签: c++


【解决方案1】:

即使是纯虚拟的析构函数也需要一个实现,因为析构函数是自动和非虚拟调用的(在每个基类链上)。

因此,如果你有一个纯虚析构函数,你最好也定义它。

否则,您将无法销毁该类的任何对象或从该类派生的类:将尝试在销毁时调用析构函数,并且链接器将抱怨找不到定义。

由于从未修复过的语法怪癖,无法在类定义中内联提供定义,而必须单独提供。

【讨论】:

  • “因此,如果你有一个纯虚拟析构函数”并不能完全回答为什么你会从一个纯虚拟析构函数开始......
  • @barakmanos:通常的短语是当您想要使类抽象并且没有任何其他好的选择时。但这只是将问题推到一边。到底为什么要这样。我依稀记得我曾经知道一些例子。我现在不记得了,所以这不是你每天都需要的东西,甚至不是每周、每月或每年都需要的东西。
  • 我理解(并同意),但我认为 OP 在问为什么(如“为什么需要它”)。
  • 我在看它,但仍然找不到答案:“析构函数需要一个实现,即使它是纯虚拟的” - 好的,但是为什么它是纯虚拟的呢? “因此,如果你有一个纯虚拟析构函数,你最好也定义它” - 那么我为什么要拥有一个纯虚拟析构函数呢?
  • 使类抽象。嗯,似曾相识。好的,这里的“抽象”表示不可实例化,除非作为基类。
【解决方案2】:

实现的纯虚函数的另一个用途是强制子类显式地请求默认行为。 Effective C++ Item 34 (paraphrasing (paracoding?)) 中给出了一个很好的例子:

class Airplane
{
public:
    virtual void fly() = 0;
};

Airplane::fly()
{
    //A default implementation
}

class ModelA : public Airplane
{
public:
    virtual void fly() { Airplane::fly(); } //explicitly use the default
};

class ModelB : public Airplane
{
public:
    virtual void fly() { Airplane::fly(); } //explicitly use the default
};

class ModelC : public Airplane
{
public:
    virtual void fly() { //different implementation }
};

这样做的目的是让客户很难意外继承他们可能不想要的默认行为。更一般地说,这个习惯用法通过分解出本质上不是默认的虚拟方法的实现来避免代码重复。

【讨论】:

  • 我认为这不是一个好的做法,因为它允许 客户端代码 调用默认处理,这可能不适合派生类实例。而是将默认设置为受保护的函数,分开。
  • @Alf,好点,也许我将如何在实践中实现它。我认为在某些情况下这种行为是可以接受的,但我想不出一个不能以更清晰的方式实施的情况。
【解决方案3】:

没有规则阻止您定义纯虚方法。这可用于强制子类提供实现,但同时也让您有机会提供方便的实现(执行常见任务)。

例如,如果xyz 派生自abc,它可以使用abcs 自己的函数定义:

struct xyz : public abc
{
    virtual void func() override
    {
        abc::func(); // explicitely calling the implementation provided by abc
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-09
    • 1970-01-01
    • 2016-06-23
    • 1970-01-01
    • 2013-07-03
    • 2010-09-25
    相关资源
    最近更新 更多