0

一个非常常见的编码实践是通过在每个类的基础上使用.h和文件将类的接口与其成员函数的实现分开。.cpp所以class Foo会用一个Foo.h头文件和一个相应的Foo.cpp文件来实现。

在泛型类的特殊情况下,这通常被抛到窗外,而是使用仅标头库来保持编译器满意,即使它确实使接口文件与实现细节混淆。

我最近遇到了一些如下编写的代码。该.h文件包含接口和一个#include包含.hpp通用成员函数实现的文件。

例如对于类型 T 的简单容器 Value.h

#ifndef VALUE_H
#define VALUE_H

template <typename T>
class Value
{
public:
    Value(T value);
    void set(T value);
    T get() const;
private:
    T data;
};

#include "Value.hpp"

#endif

和相应的Value.hpp

#ifndef VALUE_HPP
#define VALUE_HPP

template <typename T>
Value<T>::Value(T value) : data(value)
{
}

template <typename T>
void Value<T>::set(T value)
{
    data = value;
}

template <typename T>
T Value<T>::get() const
{
    return data;
}

#endif

这具有更好地分离接口和实现的优点,以及实际编译的进一步好处(在我有限的测试中)。

我的问题是,采用这种约定是否有任何隐藏的陷阱

4

2 回答 2

2

由于您需要在每个使用 Value 类的文件中包含“value.h”和“value.hpp”,因此编译时间没有任何好处。但是,如果您的意思是“它编译”与将实现放在 .cpp 文件中的解决方案,那么是的,这是有好处的。

当然有一个好处是你可以很容易地看到类提供的接口,而不用让文件被一堆实现代码弄得乱七八糟。

我不确定“value.h”和“value.hpp”的命名约定是“最佳”选择。我认为“value.inl”是第二个文件的更好名称。

于 2013-09-20T13:02:22.747 回答
1

不,此解决方案没有特殊缺陷。.hpp 文件只是另一个头文件,其中包含模板类声明的方法的定义。由于模板类的方法需要在头文件中定义,这是将声明与定义分开的方便方法。扩展名 .hpp 表明它是头文件和实现文件的混合体,并且是常用的。

于 2013-09-20T13:03:56.667 回答