1.? 為什么返回*this?
2.?
3. 友元函數的使用:需要頭文件中類內外聲明,cpp文件中實現定義哦
// Sales_data.h
#ifndef SALES_DATA_H
#define SALES_DATA_H#include <string>class Sales_data {std::string bookNo;int units_sold = 0;double revenue = 0.0;public:// 只聲明,不定義Sales_data& combine(const Sales_data&);// 友元函數:僅聲明(friend 關鍵字 + 函數簽名)friend Sales_data add(const Sales_data& lhs, const Sales_data& rhs);friend std::ostream& print(std::ostream& os, const Sales_data& item);
};// 類外函數聲明(必須!)
Sales_data add(const Sales_data& lhs, const Sales_data& rhs);
std::ostream& print(std::ostream& os, const Sales_data& item);#endif
4.template?
模板的定義必須放在頭文件中,不是因為“被其他類使用”,而是因為:
? 編譯器在實例化模板時,必須“看到”完整的定義(而不僅僅是聲明)
? 這與普通函數/類的“聲明-定義分離”模型完全不同
🧩 一、普通函數 vs 模板函數:關鍵區別
? 普通函數:可以分離聲明與定義
// utils.h void print(int x); // 聲明// utils.cpp void print(int x) { // 定義std::cout << x << "\n"; }
- 編譯?
main.cpp
?時,只需要知道?- 鏈接時,鏈接器找到?
? 成功!
? 模板函數:不能這樣分離!
// utils.h template<typename T> void print(const T& x); // 只有聲明// utils.cpp template<typename T> void print(const T& x) { // 定義std::cout << x << "\n"; }
// main.cpp #include "utils.h" print(42); // ? 編譯錯誤! print("hello"); // ? 編譯錯誤!
為什么?
- 編譯器看到?
print(42)
,需要生成?print<int>(int)
- 但它只看到了聲明,沒看到定義
- 所以無法生成具體代碼
- 鏈接時也找不到?
print<int>
,報?undefined reference
👉 模板不是函數,它是一個“生成函數的藍圖”
? 正確做法:定義放在頭文件中
// utils.h #ifndef UTILS_H #define UTILS_H#include <iostream>// 定義在頭文件中 template<typename T> void print(const T& x) {std::cout << x << "\n"; }#endif
// main.cpp #include "utils.h" // 包含了完整定義 print(42); // ? 編譯器看到定義,可以實例化 print<int> print("hello"); // ? 實例化 print<const char*>
🧠 二、為什么必須“看到定義”?
因為模板實例化發生在 編譯期(compile time),而不是鏈接期。
編譯器要做:
- 看到?
print(42)
- 推導出?
T = int
- 生成?函數代碼:
void print<int>(const int&)
- 內聯或調用
👉 這個過程需要完整的函數體(定義),而不僅僅是簽名。