首页 > 解决方案 > 构建器模式实现中的不完整类型错误

问题描述

我正在玩 Builder 模式。而且,我遇到了“不完整的返回类型”问题。实施它的正确方法应该是什么?

// HtmlElement.h

#include <iostream>
#include <string>
using namespace std;

class HtmlBuilder;
class HtmlElement
{
  string name, text;
  HtmlElement()
    {
      cout << "HtmlElement created\n";
    }
 public:
  ~HtmlElement()
    {
      cout << "HtmlElement destroyed\n";
    }

  static HtmlBuilder create();

  friend ostream& operator<<(ostream& os, const HtmlElement& obj)
  {
    return os
      << "name: " << obj.name
      << " text: " << obj.text << endl;
  }

  friend class HtmlBuilder;

};

// HtmlBuilder.h

#include "HtmlElement.h"

using namespace std;
class HtmlBuilder
{
  HtmlElement root;
 public:
  HtmlBuilder()
    {
      root.name = "root";
      root.text = "dummy";
    }
  ~HtmlBuilder()
    {

    }
  HtmlElement build() { return root; }
};

// HtmlElement.cpp

    HtmlBuilder HtmlElement::create()
    {
      return HtmlBuilder();
    }

编译器抛出与不完整类型相关的错误。

HtmlElement.cpp:4:33: error: return type 'class HtmlBuilder' is incomplete
4 | HtmlBuilder HtmlElement::create()
  |                                 ^
HtmlElement.cpp: In static member function 'static void HtmlElement::create()':
HtmlElement.cpp:6:22: error: invalid use of incomplete type 'class HtmlBuilder'
6 |   return HtmlBuilder();
  |                      ^
In file included from HtmlElement.cpp:1:
HtmlElement.h:7:7: note: forward declaration of 'class HtmlBuilder'
7 | class HtmlBuilder;

我还尝试在构建器对象中有一个指向 HtmlElement 类的指针。但是,仍然有同样的错误。

标签: c++builder

解决方案


你遇到了麻烦:

class HtmlElement
{
public:
    static HtmlBuilder create(); // requires complete definition of HtmlBuilder
                                 // -> include HtmlBuilder.h
};

class HtmlBuilder
{
public:
    HtmlElement build();         // requires complete definition of HtmlElement
                                 // -> include HtmlBuilder.h
};

即 HtmlElement 需要包含 HtmlBuilder ,反之亦然,这是一个循环包含(由于循环类型依赖性而不可避免)。

您需要通过任何合适的方式打破这种依赖关系。一种方法是让create函数返回一个指针:

HtmlBuilder* HtmlElement::create();
// possibly better a smart pointer:
std::unique_ptr<HtmlBuilder> HtmlElement::create();

然而,问题是:为什么你需要一个静态的创建者函数?这个函数除了构造函数还能做什么?如果您需要能够区分不同的构造类型,您可以通过标签类型来做到这一点(类似于std::for_each中使用的执行策略)。


推荐阅读