首先,我是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()
?
答案 0 :(得分:19)
您不需要实施文件。只需内联定义所有必需的成员(如果不需要,不要定义纯虚拟成员)。
class Magic
{
public:
Magic(void) {};
~Magic(void) {};
virtual void display()=0;
};
答案 1 :(得分:10)
如果您遵循2-files-per-class
和one-class-in-each-set-of-files
惯例,即使您正在编写抽象类,最好还是拥有.cpp
文件。
除了保持一致性之外,还有一些其他优点:如果您要为您的类系列添加非虚拟的常见行为,拥有.cpp
或实现文件可以为将来扩展提供空间,基类是添加它的正确位置。同样,.cpp
文件中的少量编辑将导致编译时间远远少于多个地方包含的.h
编辑时间。
除了惯例之外,您可以将一个类(抽象或不抽象)放在一个.h
文件中。像STL这样的图书馆一直这样做。
答案 2 :(得分:3)
不,您可以为纯虚函数添加函数definition
,但通常您不需要为纯虚函数提供函数定义。注意,您缺少Magic::display()
的函数返回类型,应该是:
void Magic::display()
{
}
答案 3 :(得分:3)
您不需要抽象类的源文件(即接口)。
此外,如果您有任何类型的虚拟方法,则还应添加虚拟析构函数(或使析构函数受保护)。
您也可以让编译器为您生成默认构造函数。如果你想要一个纯虚函数(派生类必须覆盖)
你不应该添加一个函数体,所以请离开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() {}
};
答案 4 :(得分:1)
如果您的类仅包含虚拟方法,则它实际上定义了一个接口。接口本质上表示2个实体之间的契约,没有任何实现依赖性。因此,作为一个好的设计实践,您不仅不需要.cpp
文件,没有它也会更好。
由于你正在使用VS,你也可以使用MS扩展__interface代替具有纯虚方法的类(注意,它不是可移植的)。