[英]C++ initialize const member with mutator method
Suppose the following class exists (which I cannot change).假设存在以下类(我无法更改)。
class TheirClass {
public:
TheirClass();
TheirClass(const TheirClass&) = delete;
TheirClass& operator=(const TheirClass&) = delete;
TheirClass(TheirClass&&) = delete;
void FinishInitialization();
}
I would like to use it in my class like so.我想像这样在我的课堂上使用它。
class MyClass {
private:
const TheirClass their_class_;
}
If the copy and move constructors were not deleted, I could do something like this.如果复制和移动构造函数没有被删除,我可以做这样的事情。
TheirClass CreateTheirClass() {
TheirClass their_class;
their_class.FinishInitialization();
return their_class;
}
MyClass::MyClass() : their_class_(CreateTheirClass()) {}
Currently my solution is to use pointers.目前我的解决方案是使用指针。
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()) {}
But this seems to add unnecessary complexity and a needless performance hit (storing the object on the heap rather than the stack).但这似乎增加了不必要的复杂性和不必要的性能损失(将对象存储在堆上而不是堆栈上)。
How can I have a const TheirClass
as member in my class while still being able to call TheirClass::FinishInitialization
(once, upon initialization of my class)?我怎样才能在我的班级中有一个const TheirClass
作为成员,同时仍然能够调用TheirClass::FinishInitialization
(一次,在我的班级初始化时)?
You can make a wrapper class that calls FinishInitialization
in its constructor, but only exposes the instance as a const
.您可以创建一个在其构造函数中调用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_;
};
Use the wrapper instead:改用包装器:
class MyClass
{
public:
MyClass();
// ...
private:
const TheirClassWrapper their_class_;
}
You then use their_class_->whatever()
or *their_class_
to access things.然后您使用their_class_->whatever()
或*their_class_
来访问事物。 It looks like a pointer, but it will get trivially inlined by your compiler.它看起来像一个指针,但它会被你的编译器简单地内联。
A potentially more generic solution to this is:一个可能更通用的解决方案是:
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_;
};
This allows you to run some arbitrary function in the InitWrapper
constructor, while still only exposing the const T
view of things.这允许您在InitWrapper
构造函数中运行一些任意函数,同时仍然只公开事物的const T
视图。
MyClass::MyClass()
: their_class_([](TheirClass& x) { x.FinishInitialization(); })
{ }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.