【问题标题】:Constraint on constructor calling构造函数调用的约束
【发布时间】:2018-10-26 17:26:57
【问题描述】:

我设计了一个类 InputField 有一个带有 2 个参数的构造函数:explicit InputField(InputFieldIndex uiIndex, QString sName) noexcept;

我将这个类存储在QVector 中,所以很遗憾,我必须添加一个默认构造函数。在软件设计方面,这对我不利(因为我对uiIndex 有限制)。 有没有办法只允许QT(在我的情况下为QVector)调用默认构造函数?宏指令还是预处理指令?

【问题讨论】:

  • 改用std::vector 怎么样?否则,故事化 std::optional<InputField> 或其他一些代理类型可能也值得考虑。
  • @FrançoisAndrieux 我不能,这是一个完整的 Qt 应用程序。
  • “完整的 Qt”是什么意思?有人强迫你使用 QVector?
  • @Milleras 你不能使用 C++ 标准库吗?
  • @Milleras 你禁止使用标准类型吗?否则,QVector<std::optional<InputField>> 似乎应该完成这项工作。

标签: c++ qt


【解决方案1】:

QVector 不需要调用默认构造函数;毕竟std::vector 不会——除非您使用其中一种需要该构造函数的方法。您只需在QVector 中禁用默认构造:

#define QVECTOR_NON_DEFAULT_CONSTRUCTIBLE(Type) \
template <> QVector<Type>::QVector(int) = delete; \
template <> void QVector<Type>::resize(int newSize) { \
   Q_ASSERT(newSize <= size()); \
   detach(); \
} \
template <> void QVector<Type>::defaultConstruct(Type*, Type*) { Q_ASSERT(false); }

然后,将宏放在与 Q_DECLARE_METATYPE 相同的位置:就在声明类型的位置:

class InputField {
  ...
};
QVECTOR_NON_DEFAULT_CONSTRUCTIBLE(InputField)

然后您可以使用 QVector&lt;InputField&gt;,但具有与 std::vector 相同的限制。

【讨论】:

  • 你建议扩展 QVector 吗?否则,我该如何使用你的宏?
  • @JosephGarnier 该宏提供了QVector 方法的特化。这就是模板类型的美妙之处:您可以轻松地在特殊情况下替换它们的零碎!
  • 我收到错误:“函数 QVector::QVector(int size) 不能在当前范围内专门化”(对我来说这很正常)
  • 你做了我上面没有做的事情,因为上面的工作很好。回想一下,这种特化需要发生在命名空间范围内,而不是类范围内。事实上,如果有的话,你需要专门研究 Qt 的命名空间。否则在全局范围内。
  • 清理我的项目没有任何改变,但我发现了错误。您必须在函数中返回类型之前添加inline。否则,效果很好!谢谢。
【解决方案2】:

您可以尝试将QVector&lt;InputField&gt; 设为朋友班。

考虑以下玩具示例:

class Foo {
    // Grant QVector<Foo> access to this class' internals
    friend class QVector<Foo>;
public:
    explicit Foo(int a, bool b) {
        // Empty
    }
private:
    Foo() {
        // Callable by this class and QVector<Foo>.
    }
};

这样,可以将Foo 的实例存储在QVector&lt;Foo&gt; 中:

QVector<Foo> myList;
myList << Foo(1, true) << Foo(2, false);

但是,例如以下内容失败:

Foo foo;

【讨论】:

  • 没有参数的构造函数不需要显式。
  • 好主意!它有效,谢谢。我添加了InputField() = default;friend class QVector&lt;InputField&gt;;
  • @SergeyA:感谢您的提示 ;-) 我会更新答案。
  • @Milleras 请注意,这意味着现在可以使用QVector 访问默认构造的实例,这意味着您仍然可以使用无效实例。就目前而言,发现这种情况并不一定容易。
  • 这个解决方案将FooQVector 紧密绑定在一起,不要介意存在默认构造函数——也许Foo 使用不可默认构造的成员?目标是使QVector 可以使用非默认可构造的Foo,而无需更改Foo 的任何内容。这清楚地指出了解决方案应该是什么:不可复制类型FooQVector 成员的特化。
猜你喜欢
  • 1970-01-01
  • 2020-02-26
  • 1970-01-01
  • 1970-01-01
  • 2019-02-07
  • 1970-01-01
  • 1970-01-01
  • 2012-10-12
  • 1970-01-01
相关资源
最近更新 更多