C ++使用mutator方法初始化const成员

时间:2020-03-04 00:29:05

标签: c++

假设存在以下类(我不能更改)。

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(一次在班级初始化后)?

1 个答案:

答案 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(); })
{ }
相关问题