iT邦幫忙

2025 iThome 鐵人賽

DAY 20
1
Software Development

30 天 Effective C++ 大挑戰!!系列 第 20

[Day 20] Templates and Generic Programming III

  • 分享至 

  • xImage
  •  

隨著閱讀進度的推進,愈發能感受到概念的複雜與深奧。若遇到不理解的部分,請隨時回顧前面的文章,一起在後續的學習中更游刃有餘!

45: Use member function templates to accept "all compatible types"

知識點 15 所述,C++ 支持衍生類別指標隱式轉換為基底類別指標。但在模板類中,可能會發生 SmartPtr<Student> 與其衍生類別 SmartPtr<Yoyo> 為不同類型。即使 Student 與 Yoyo 在繼承關係中,模板實例之間並無繼承關係。

成員函式模板可模仿智慧指標間的隱式型別轉換。例如透過 template<typename Yoyo> 泛型建構函式實現:

template <typename Student>
class SmartPtr {
public:
    explicit SmartPtr(Student* realPtr) {}
    template<typename Yoyo>
    SmartPtr(const SmartPtr<Yoyo>& other) : heldPtr(other.get()) {}
};

然而,這種設計可能允許無效的不合法類型轉換,例如 SmartPtr<double>SmartPtr<int>互相轉換。因此需利用原始 C++ 的非模板型別隱式轉換進行約束,即當無法隱式轉換時應回報編譯錯誤。使用成員函式模板實現所有兼容的型別轉換,仍需顯式提供預設非模板的建構函式和賦值函式,以避免不必要的行為偏差或預期外的情況。

順帶一提,範例中使用的「初始化列表」在物件建立時就直接初始化成員變量。而「賦值」則是在物件建立後,透過賦值運算子進行操作。初始化列表通常效率較高,特別是在處理參考、const 成員或 class 成員時。

46. Define non-member functions inside templates when type conversions are desired

一般情況下,非模板類提供非成員函式以支持混合型別。但若使用模板類,在 type deduction 階段不會考慮隱式轉型函式,導致 RationalTP<int> * int 等混合型別操作無法編譯。

將非成員函式聲明為模板類的 friend 函式即可解決。其在模板類中自動宣告並生成具體型別,此時隱式型別轉換函式得以生效。知識點 19 有討論到相關的成員訪問權限設計。

template <typename T>
class RationalTP {
public:
    RationalTP(const T& numerator = 0, const T& denominator = 1)
    : m_numerator(numerator), m_denominator(denominator) {}

    const T numerator() const { return m_numerator; }
    const T denominator() const { return m_denominator; }

    friend const RationalTP operator*(const RationalTP &lhs, const RationalTP &rhs) {
        return RationalTP(lhs.numerator() * rhs.numerator(), lhs.denominator() * rhs.denominator());
    }

private:
    T m_numerator;
    T m_denominator;
};

上一篇
[Day 19] Templates and Generic Programming II
下一篇
[Day 21] Templates and Generic Programming IV
系列文
30 天 Effective C++ 大挑戰!!30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言