Abe*_*bee 4 c++ fluent builder c++builder c++11
我正在尝试使用流畅的界面实现构建器模式,以在 C++ 中构建对象。我希望构建器遵循 CRTP 模式。在 Java 中,我会执行类似于以下代码的操作。我如何在 C++ 中做同样的事情?
下面是一些具有基类和派生类的 java 代码。派生类的构建器继承了基类的构建器..
// Base class
public abstract class BaseClass {
private final int base_class_variable;
BaseClass(final Builder <?> builder) {
this.base_class_variable = builder.base_class_variable;
}
public abstract static class Builder <B extends Builder> {
int base_class_variable;
public B setBaseClassVariable(final int variable) {
this.base_class_variable = variable;
return self();
}
protected abstract B self();
}
}
// Derived class
public final class DerivedClass extends BaseClass {
private final int derived_class_variable;
private DerivedClass(final Builder builder) {
super(builder);
this.derived_class_variable = derived_class_variable;
}
public static Builder builder() {
return new Builder();
}
public static final class Builder extends BaseClass.Builder <Builder> {
private int derived_class_variable;
public Builder setDerivedClassVariable(final int variable) {
this.derived_class_variable = variable;
return self();
}
public DerivedClass build() {
return new DerivedClass(this);
}
@Override
protected Builder self() {
return this;
}
}
}
// Creating an instance of DerivedClass
DerivedClass dInstance = DerivedClass.builder()
.setBaseClassVariable(5)
.setDerivedClassVariable(10)
.build();
Run Code Online (Sandbox Code Playgroud)
这是在 C++ 中执行此操作的一种方法:
template <typename T>
class Builder {
public:
static T builder() { return {}; }
T & build() {return static_cast<T&>(*this); }
};
template <typename T>
class BaseClass : public Builder<T> {
int base_class_variable;
public:
T& setBaseClassVariable(int variable) {
base_class_variable = variable;
return static_cast<T&>(*this);
}
};
class DerivedClass : public BaseClass<DerivedClass> {
int derived_class_variable;
public:
DerivedClass& setDerivedClassVariable(int variable) {
derived_class_variable = variable;
return *this;
}
};
int main()
{
// Creating an instance of DerivedClass
DerivedClass dInstance = DerivedClass::builder()
.setBaseClassVariable(5)
.setDerivedClassVariable(10)
.build();
}
Run Code Online (Sandbox Code Playgroud)
这是一个仅允许在右值引用(由构建器返回)上更改值的示例:
#include <utility>
template <typename T>
class Builder {
public:
static T builder() { return {}; }
T & build() {return static_cast<T&>(*this); }
};
template <typename T>
class BaseClass : public Builder<T> {
int base_class_variable;
public:
T&& setBaseClassVariable(int variable) && {
base_class_variable = variable;
return std::move(static_cast<T&>(*this));
}
};
class DerivedClass : public BaseClass<DerivedClass> {
int derived_class_variable;
public:
DerivedClass&& setDerivedClassVariable(int variable) && {
derived_class_variable = variable;
return std::move(*this);
}
};
int main()
{
// Creating an instance of DerivedClass
DerivedClass dInstance = DerivedClass::builder()
.setBaseClassVariable(5)
.setDerivedClassVariable(10)
.build();
//dInstance.setBaseClassVariable(34); // will not compile
}
Run Code Online (Sandbox Code Playgroud)
这是第三个解决方案,它使用Proto由builder(). 必须使用using声明来指定私有成员函数,以便Proto. 最后,该build()函数返回DerivedClass不公开成员函数的 。
template<typename T>
class BaseClass;
class DerivedClass;
template <typename T>
class Proto : public T {
public:
using BaseClass<T>::setBaseClassVariable;
using T::setDerivedClassVariable;
};
template <typename T>
class Builder {
public:
static Proto<T> builder() { return {}; }
T& build() { return static_cast<T&>(*this); }
};
template <typename T>
class BaseClass : public Builder<T> {
int base_class_variable;
Proto<T>& setBaseClassVariable(int variable) {
base_class_variable = variable;
return static_cast<Proto<T>&>(*this);
}
friend class Proto<T>;
};
class DerivedClass : public BaseClass<DerivedClass> {
int derived_class_variable;
Proto<DerivedClass>& setDerivedClassVariable(int variable) {
derived_class_variable = variable;
return static_cast<Proto<DerivedClass>&>(*this);
}
friend class Proto<DerivedClass>;
};
int main()
{
// Creating an instance of DerivedClass
DerivedClass dInstance = DerivedClass::builder()
.setBaseClassVariable(5)
.setDerivedClassVariable(10)
.build();
//dInstance.setBaseClassVariable(34); // cannot access private member
}
Run Code Online (Sandbox Code Playgroud)