c++ - 在仅 header 库的类定义中实现有什么不同?

标签 c++ header-files

我正在开发一个大量使用模板的库,因此我决定将其设为仅包含 header 的库。由于声明和实现在同一个文件中,我现在可以同时进行。所以我可以在这两种风格之间做出选择:

// seperate declaration and implementation

template <typename T>
class Klass {
public:
    void do_something();
};

template <typename T>
void Klass<T>::do_something()
{
    // do something
}


// or both at the same time

template <typename T>
class Klass {
public:
    void do_something()
    {
        // do something
    }
};

我想知道这两者对于编译器是否有区别。如果不是,您会推荐哪一个作为更好的做法?

最佳答案

如果合并定义和实现,您将无法解决交叉/循环依赖问题。



例如:

1。使用你的第二个选项

home.hpp

#ifndef HOME_HPP
# define HOME_HPP

# include <string>

# include "human.hpp"

template <typename T>
class   Home
{
public:
  Home()
    :
    color_("white"),
    inhabitant_(this)
  {
  }

  void  set_color(const std::string& color)
  {
    color_ = color;
  }

private:
  std::string   color_;
  Human<T>      inhabitant_;
};

#endif

human.hpp

#ifndef HUMAN_HPP
# define HUMAN_HPP

# include <string>

// Cannot include the other header here because it already includes us
//# include "house.hpp" 

// So we do a forward declaration:
template<typename T>
class Home;

template <typename T>
class   Human
{
public:
  Human(Home<T>* house)
    :
    house_(house)
  {
  }

  void  paint(const std::string& color)
  {
   // Oops, we can't use House in our implementation
   // because it is only forward declared
   //house_->set_color(color); 
  }

private:
  Home<T>*     house_;
};

#endif

您不能使用其他对象。



而如果您将实现拆分到另一个文件中:

2。使用您的第一个选项

home.hpp

#ifndef HOME_HPP
# define HOME_HPP

# include <string>

# include "human.hpp"

template <typename T>
class   Home
{
public:
  Home();

  void  set_color(const std::string& color);

private:
  std::string   color_;
  Human<T>      inhabitant_;
};

#endif

home.ipp

#ifndef HOME_IPP
# define HOME_IPP

# include "home.hpp"

template<typename T>
Home<T>::Home()
  :
  color_("white"),
  inhabitant_(this)
{
}

template<typename T>
void  Home<T>::set_color(const std::string& color);
{
  color_ = color;
}

#endif

human.hpp

#ifndef HUMAN_HPP
# define HUMAN_HPP

# include <string>

template<typename T>
class Home;

template <typename T>
class   Human
{
public:
  Human(Home<T>* house);

  void  paint(const std::string& color);

private:
  Home<T>*     house_;
};

#endif

human.ipp

#ifndef HUMAN_IPP
# define HUMAN_IPP

# include "human.hpp"
# include "house.ipp"

template<typename T>
Human<T>::Human(Home<T>* house)
  :
  house_(house)
{
}

template<typename T>
void  Human<T>::paint(const std::string& color)
{
 house_->set_color(color); 
}

#endif

事情更顺利



3。其他注意事项

  • 也有人会争辩说,您应该将代码放在多个文件中,原因与您不将整个项目编码在一个文件中的原因相同,只是为了拆分内容,使它们更易于理解。
  • 作为最后的奖励点,为了与 .hpp/.cpp 文件对称,这将让每个开发人员内心深处(对某些人来说睡得很深)的完美主义者保持沉默 :)

关于c++ - 在仅 header 库的类定义中实现有什么不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25890133/

相关文章:

c - C 中的一次性伪通用 header

c++ - 返回类型是实例化的还是简单分配的值

c++ - 如何配置 VS Code 使其在程序运行后不会关闭控制台

c++ - 如果没有重载赋值运算符,我怎么能复制结构 vector ?

c++ - 找到破坏编译的#define

c++ - 在 C++ 中声明、操作和访问未对齐的内存

c - 将头文件包含到静态库中

c++ - 如何用头文件确定函数定义?

linux - FC12下的Pulseaudio头文件

c++ - 内部类和封闭类分开定义