簡體   English   中英

在靜態函數中返回對象而不是構建對象有什么好處?

[英]What is the advantage of returning an object in a static function instead of building it?

以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中看到了這種選擇,我無法理解它的優點是什么以及缺少該構造函數的原因。

靜態創建方法很方便,因為它們不需要創建冗余對象,可以添加到它們創建的對象的代碼中。使用創建方法insteed構造函數的原因有很多。 這里僅僅是少數:

  1. 必須始終使用有效的對象創建來完成構造函數。 在構造函數中使用異常是一種非常糟糕的做法。 如果無法創建對象,例如由於參數不正確或初始化順序不正確,我們可以做些什么? 在創建方法的情況下,您可以簡單地返回nullptr或一些“錯誤的”對象類型。

  2. 如果我們想要自定義對象創建而不更改其代碼。 例如,我們想要構建一個對象並對其進行配置,或者我們沒有可用參數的構造函數。 包裝函數允許您在不觸及類代碼的情況下解決問題。 這適用於給定的示例, 如您所見fromString在構造函數調用之前解析字符串參數。

  3. 我們不知道要構建什么樣的對象。 這是在運行時決定的。 通常,我們可以返回基礎對象,並在包裝​​器中選擇必要的類。 這允許您不更改具體對象選擇的主代碼。

  4. 我們希望控制所有對象的創建,以消除可能的內存泄漏。 例如,在取消初始化庫時,即使用戶忘記了,也要釋放所有資源。

我建議您熟悉設計模式,特別是使用сreational模式

這實際上是一個很好的問題。

原因因情景而異,但涉及以下問題:

  • 構造函數的可讀性如何?
  • 我是創建人工對象還是不必要地重復條件,以便根據初始化列表編寫構造函數?
  • 我的構造函數是否有一個含糊不清的構造函數意味着執行不同類型的構造?
  • 我的構造函數在做什么而不必在代碼中拼出一個名字是顯而易見的?

以上所有都將涉及一定程度的主觀性。

假設的例子,猜測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);
}

這當然是可能的,推遲到一個私有構造函數,它接受一個專門的函數對象。 但是圖書館的作者可能認為這太過神秘或難以維護。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM