25

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

魔法.h

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

魔术.cpp

#include "Magic.h"


Magic::Magic(void)
{
}


Magic::~Magic(void)
{
}

现在,如您所知,我无法将以下内容添加到 cpp 文件中。

Magic::display()
{
}

那么,我真的需要一个抽象类的 .cpp 文件吗?或者,我是否错误地调用display()了 .cpp 文件?

4

5 回答 5

25

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

class Magic
{
public:
    Magic(void) {};
    ~Magic(void) {};
    virtual void display()=0;
};
于 2012-12-22T08:50:30.967 回答
13

如果您遵循2-files-per-classand约定,那么即使您正在编写抽象类one-class-in-each-set-of-files,也最好有一个文件。.cpp

除了保持一致性之外,还有其他一些优点:拥有一个.cpp或实现文件为您提供了未来扩展的空间,如果您要向您的类家族添加非虚拟通用行为,则基类是正确的地方添加它。与从多个位置包含的文件相比,文件中的微小编辑也.cpp将导致编译时间短得多。.h

除了约定之外,您可以很好地将一个类(抽象或非抽象)放在一个.h文件中。诸如 STL 之类的库一直都在这样做。

于 2012-12-22T08:49:41.977 回答
4

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

此外,如果您有任何类型的虚拟方法,您也应该添加一个虚拟析构函数(或使析构函数受保护)。您也可以简单地让编译器为您生成一个默认构造函数。如果你想要一个纯虚函数(派生类必须重写),你不应该添加函数体,所以不要添加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() {}
};
于 2012-12-22T09:08:03.007 回答
3

不,您可以definition为纯虚函数添加函数,但通常您不需要为纯虚函数提供函数定义。请注意,您缺少的函数返回类型Magic::display()应该是:

void Magic::display()
{
}
于 2012-12-22T08:42:52.333 回答
1

如果你的类只包含方法,它实际上定义了一个接口。接口本质上代表 2 个实体之间的契约,没有任何实现依赖。因此,作为一种良好的设计实践,您不仅不需要该.cpp文件,而且最好没有它。

由于您使用的是 VS,因此您还可以将 MS 扩展__interface用于接口而不是具有纯虚拟方法的类(请注意,它不可移植)。

于 2012-12-22T09:01:34.657 回答