假设存在以下类(我不能更改)。
class TheirClass {
public:
TheirClass();
TheirClass(const TheirClass&) = delete;
TheirClass& operator=(const TheirClass&) = delete;
TheirClass(TheirClass&&) = delete;
void FinishInitialization();
}
我想像这样在课堂上使用它。
class MyClass {
private:
const TheirClass their_class_;
}
如果没有删除copy和move构造函数,我可以做这样的事情。
TheirClass CreateTheirClass() {
TheirClass their_class;
their_class.FinishInitialization();
return their_class;
}
MyClass::MyClass() : their_class_(CreateTheirClass()) {}
目前,我的解决方案是使用指针。
class MyClass {
private:
const std::unique_ptr<const TheirClass> their_class_;
}
std::unique_ptr<TheirClass> CreateTheirClass() {
auto their_class = std::make_unique<TheirClass>();
their_class->FinishInitialization();
return their_class;
}
MyClass::MyClass() : their_class_(CreateTheirClass()) {}
但这似乎增加了不必要的复杂性和不必要的性能损失(将对象存储在堆而不是堆栈上)。
如何在班级中拥有const TheirClass
作为成员,同时仍然能够调用TheirClass::FinishInitialization
(一次在班级初始化后)?
答案 0 :(得分:0)
您可以创建一个包装类,该包装类在其构造函数中调用FinishInitialization
,但仅将实例公开为const
。
class TheirClassWrapper final
{
public:
/// The question didn't specify `args`, but I assume you want them here
template <typename... Args>
explicit TheirClassWrapper(Args&&... args)
: impl_()
{
impl_.FinishInitialization(std::forward<Args>(args)...);
}
const TheirClass& operator*() const noexcept { return impl_; }
const TheirClass* operator->() const noexcept { return &impl_; }
private:
TheirClass impl_;
};
改为使用包装器:
class MyClass
{
public:
MyClass();
// ...
private:
const TheirClassWrapper their_class_;
}
然后,您可以使用their_class_->whatever()
或*their_class_
来访问内容。它看起来像一个指针,但是编译器会对其进行内联。
对此可能更通用的解决方案是:
template <typename T>
class InitWrapper final
{
public:
template <typename FInit>
explicit InitWrapper(FInit&& init)
{
init(impl_);
}
const T& operator*() const noexcept { return impl_; }
const T* operator->() const noexcept { return impl_; }
private:
T impl_;
};
这使您可以在InitWrapper
构造函数中运行某些任意函数,同时仍然仅显示事物的const T
视图。
MyClass::MyClass()
: their_class_([](TheirClass& x) { x.FinishInitialization(); })
{ }