c++ - 构建器模式实现中的不完整类型错误
问题描述
我正在玩 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 类的指针。但是,仍然有同样的错误。
解决方案
你遇到了麻烦:
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中使用的执行策略)。
推荐阅读
- python - 如何有效地将多个功能应用于数据框?
- dart - Dart:以字符串为参数的函数作为回调中的参数
- html - 仅在事件后加载 amp-list 数据
- authentication - Kentico 12 - 如何将单个页面设置为需要身份验证?
- jquery - 如果 jquery 中的空在 laravel 中不起作用,则返回
- python - 如何从csv文件中选择3列系数的数据
- php - php xpath替换不具有一定的价值
- python - Django - 初始值模型
- spring-boot - Spring Boot Actuator - 多个健康端点
- javascript - 为什么“in”运算符会使用字符串文字而不是记录错误来引发错误?