我需要为抽象类创建一个.cpp文件吗?

26

首先,我是C++的新手。我为每个C++类打开一个头文件。现在我需要创建一个抽象类。以下是我的代码:

Magic.h

#pragma once
class Magic
{
public:
    Magic(void);
    ~Magic(void);
    virtual void display()=0;
};

Magic.cpp

#include "Magic.h"


Magic::Magic(void)
{
}


Magic::~Magic(void)
{
}

现在,正如你所知道的,我不能将以下内容添加到cpp文件中。

Magic::display()
{
}

所以,我是否真的需要为一个抽象类创建一个 .cpp 文件?否则,在 .cpp 文件中调用 display() 是不正确的吗?

5个回答

26

你不需要一个实现文件。只需内联定义所有所需成员(如果不需要,请勿定义纯虚拟成员)。

class Magic
{
public:
    Magic(void) {};
    ~Magic(void) {};
    virtual void display()=0;
};

没有纯虚函数,我们就不能把一个类称为“抽象类”,对吗?因为这样我们就可以创建它的对象。 - PeakGen
是的,抽象类至少有一个纯虚函数。但这并不意味着你不能为该函数提供实现(即使你提供了实现,它仍然是抽象的)。 - Mat
好的。但是当我尝试使用Visual Studio类向导扩展该类时,它会显示“项目中找不到基类Majic”。现在怎么办? - PeakGen
那与抽象类有没有关系无关。你可能在某个地方漏掉了 #include "Magic.h" - Mat
1
包含纯虚函数的类的析构函数也应该是虚的。这是为了考虑到有一个基类指针,因此在删除时能够调用正确的析构函数。 - Moshe Rabaev

14
如果您遵循“每个类有两个文件”和“每组文件中只有一个类”的规则,即使编写抽象类,最好也有一个 .cpp 文件。除了保持一致性外,还有其他几个优点:具有 .cpp 或实现文件可以为您将来扩展留出空间,如果要向类族添加非虚通用行为,则基类是正确的地方添加它。此外,在 .cpp 文件中进行小的编辑将导致比从多个位置包含的 .h 中的编辑更少的编译时间。
撇开约定不谈,您完全可以在一个单独的 .h 文件中放置一个类(无论是否抽象)。像 STL 这样的库经常这样做。

4
我遵循这个规范的另一个原因是为了检查Magic.h是否能够成功编译。Magic.cpp只包含单个include,这可以防止出现难以发现的错误,其中Magic.h依赖于另一个类但未进行引用或前向声明,并且通常是间接地获取它。结果是Foo.cpp可能会编译通过,但Bar.cpp不会,你会忽略Magic.h作为原因,因为它是两者共同的。 - MSalters

4

抽象类(即接口)不需要源文件。

另外,如果您有任何类型的虚拟方法,应该添加一个 virtual 析构函数,或者将析构函数设置为 protected。 同时,您可以让编译器为您生成默认构造函数。如果您想要一个纯虚函数(派生类必须覆盖),则不应添加函数体,因此请省略 void Magic::display() {}。并且由于您必须为析构函数提供一个函数体,所以您可以在内联中定义它:

struct Magic {
    // use default constructor
    virtual void display() =0; // pure virtual function
    virtual ~Magic(); // virtual destructor
};

inline Magic::~Magic()
{
}

甚至更简单:
#pragma once

struct Magic {
    virtual void display() =0;
    virtual ~Magic() {}
};

3
不需要为纯虚函数提供函数定义,但可以添加一个名为definition的功能。请注意,您缺少Magic::display()的函数返回类型,应该是:
void Magic::display()
{
}

1
如果你的类只包含虚方法,那么它实际上定义了一个接口。接口本质上代表着两个实体之间的契约,没有任何实现依赖。因此,作为良好的设计实践,不仅你不需要`.cpp`文件,而且最好不要有它。
由于你正在使用VS,你也可以使用MS扩展__interface来代替具有纯虚方法的类(注意,这不是可移植的)。

但我无法扩展它!当我试图使用Visual Studio类创建向导在“Sp”类中扩展它时,它会显示“此项目中未找到基类”。 - PeakGen
@Sepala,我不明白你在说什么。 - SomeWittyUsername

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接