在静态函数中返回对象而不是构建对象有什么好处?

问题描述 投票:4回答:2

以Qt框架的以下文档为例,即使我的问题不是Qt特定的:

https://doc.qt.io/qt-5/qversionnumber.html

您可以找到静态公共成员函数:

QVersionNumber fromString(const QString &string, int *suffixIndex = nullptr)

代替:

QVersionNumber(const QString &string, int *suffixIndex = nullptr)

在构造函数列表中。

我已经看到在许多库API中做出的这种选择,我无法理解它的优点是什么以及缺少该构造函数的原因。

c++ constructor static-methods
2个回答
1
投票

这实际上是一个很好的问题。

原因因情景而异,但涉及以下问题:

  • 构造函数的可读性如何?
  • 我是创建人工对象还是不必要地重复条件,以便根据初始化列表编写构造函数?
  • 我的构造函数是否有一个含糊不清的构造函数意味着执行不同类型的构造?
  • 我的构造函数在做什么而不必在代码中拼出一个名字是显而易见的?

以上所有都将涉及一定程度的主观性。

假设的例子,猜测QVersionNumber的内部,

你会如何在初始化列表中写这个?

QVersionNumber 
QVersionNumber::fromString(const QString &string, int *suffixIndex)
{
    std::optional<QVersionNumber> result;
    auto first = string.begin();
    auto last = string.end();
    auto opt_major = maybe_extract_decimal(first, last); // modifies first
    if (not opt_major.has_value())
        result.emplace();
    else
    {
        auto opt_minor = maybe_extract_decimal(first, last); // modifies first
        if (not opt_major.has_value())
            result.emplace(*opt_major);
        else
            result.emplace(*opt_minor);
    }
    if (suffixIndex)
      *suffixIndex = int(std::difference(string.begin(), first);
    return *std::move(result);
}

这当然是可能的,推迟到一个私有构造函数,它接受一个专门的函数对象。但是图书馆的作者可能认为这太过神秘或难以维护。


1
投票

静态创建方法很方便,因为它们不需要创建冗余对象,可以添加到它们创建的对象的代码中。使用创建方法insteed构造函数的原因有很多。这里仅仅是少数:

  1. 必须始终使用有效的对象创建来完成构造函数。在构造函数中使用异常是一种非常糟糕的做法。如果无法创建对象,例如由于参数不正确或初始化顺序不正确,我们可以做些什么?在创建方法的情况下,您可以简单地返回nullptr或某些“错误”对象类型。
  2. 如果我们想要自定义对象创建而不更改其代码。例如,我们想要构建一个对象并对其进行配置,或者我们没有可用参数的构造函数。包装函数允许您在不触及类代码的情况下解决问题。这适用于给定的示例,as you can seefromString在构造函数调用之前解析字符串参数。
  3. 我们不知道要构建什么样的对象。这是在运行时决定的。通常,我们可以返回基础对象,并在包装​​器中选择必要的类。这允许您不更改具体对象选择的主代码。
  4. 我们希望控制所有对象的创建,以消除可能的内存泄漏。例如,在取消初始化库时,即使用户忘记了,也要释放所有资源。

我建议你熟悉设计模式,尤其是сreational pattern

© www.soinside.com 2019 - 2024. All rights reserved.