c++ 杂记
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&)
- 内联或调用
👉 这个过程需要完整的函数体(定义),而不仅仅是签名。