// point.h
#pragma once
#include <iostream>
class Point {
public:
Point(int x, int y);
// ... 其他成员函数 ...
private:
int x_;
int y_;
// 方案 A:声明为友元(如果需要访问 private 成员)
friend std::ostream& operator<<(std::ostream& os, const Point& p);
// 方案 B:如果只是用 public 接口,甚至不需要 friend
// int getX() const { return x_; }
// int getY() const { return y_; }
};
// 注意:函数原型必须写在类外面!
std::ostream& operator<<(std::ostream& os, const Point& p);
// point.cpp
#include "point.h"
Point::Point(int x, int y) : x_(x), y_(y) {}
// 实现 operator<<
std::ostream& operator<<(std::ostream& os, const Point& p) {
os << "[" << p.x_ << ", " << p.y_ << "]";
return os;
}
#include "point.h"
#include <iostream>
int main() {
Point p(1, 2);
std::cout << p << std::endl;
}
避免多重定义(ODR规则)
如果你把函数的定义(函数体)直接写在
.h文件里,并且这个头文件被多个.cpp文件包含,那么链接器会发现同一个函数有多个定义,导致链接错误。.cpp文件通常只会被编译一次,所以把定义放在这里最安全。
减少编译依赖
如果把实现放在
.cpp里,当你修改operator<<的内部逻辑时,只需要重新编译point.cpp,而不需要重新编译所有包含了point.h的文件。这能显著加快大型项目的编译速度。
符合封装原则
类的接口(
.h)告诉用户“有什么”,类的实现(.cpp)隐藏了“怎么做”。