当前位置: 首页 > news >正文

输入输出流重载说明:std::ostream operator<<(std::ostream os, const Vector v)

首先这是一个函数,函数名字是operator<<,函数的输出类型是std::ostream&,输入类型是std::ostream& const Vector& v相当于(std::cout << v)的重载后的输出可以是std::cout以便格式化输出Vector类型之后还能够继续链式输出其他内容。

// 输入输出流重载
#include <iostream>
struct Vector {
double x, y;
};
// 输出流重载
std::ostream& operator<<(std::ostream& os, const Vector& v) {
os << "(" << v.x << ", " << v.y << ")";
return os;
}
// 输入流重载
std::istream& operator>>(std::istream& is, Vector& v) {
is >> v.x >> v.y;
return is;
}
int main() {
Vector v1, v2;
// 输入
std::cout << "Enter Vector 1 (x y): ";
std::cin >> v1; // 例如输入: 1.0 2.0
std::cout << "Enter Vector 2 (x y): ";
std::cin >> v2; // 例如输入: 3.0 4.0
// 输出
std::cout << "Vector 1: " << v1 << std::endl; // 输出: Vector 1: (1.0, 2.0)
std::cout << "Vector 2: " << v2 << std::endl; // 输出: Vector 2: (3.0, 4.0)
return 0;
}
2.2.3 函数运算符重载
class Adder {
public:
int operator()(int a, int b) {
return a + b;
}
};
Adder add;
int result = add(3, 4); // 看起来像函数调用,实际是调用 operator()
// 匿名函数对象
std::cout << Adder()(3, 4) << std::endl;

2.3 继承

概念:继承允许我们创建一个新类(派生类),这个新类会继承一个基类的属性行为,实现代码的重用和类之间的层次关系。

核心思想:提取出一类物品的公共属性和行为。比如猫狗鸟等都属于动物,动物就可以作为父类。

继承是多态的基础。

子类可以对父类的成员函数进行重写。虚函数的重写是为了实现多态。

2.3.1 语法格式

// class Manager : public Employee {
#include <iostream>
#include <string>
// 基类:员工
class Employee {
public:
// 基类的构造函数
Employee(std::string name, int id, double salary)
: m_name(name),
m_id(id),
m_salary(salary) {}
// 基类的成员函数
void work() {
std::cout << m_name << " (ID: " << m_id << ") is working." << std::endl;
}
void showInfo() {
std::cout << "Name: " << m_name << ", ID: " << m_id << ", Salary: " << m_salary << std::endl;
}
protected: // protected成员在基类和派生类中都可以访问
std::string m_name;
int m_id;
double m_salary;
};
// 派生类:经理,公有继承自Employee
class Manager : public Employee {
public:
// 派生类的构造函数,需要调用基类的构造函数来初始化基类部分
Manager(std::string name, int id, double salary, double bonus)
: Employee(name, id, salary),
m_bonus(bonus) {} // 初始化列表
// 派生类新增的成员函数
void manageTeam() {
std::cout << m_name << " is managing the team." << std::endl;
}
// 派生类可以重写(覆盖)基类的函数
void showInfo() {
// 先调用基类的showInfo()显示共同信息
Employee::showInfo(); // 使用作用域解析符调用基类版本
// 再显示派生类特有的信息
std::cout << "Bonus: " << m_bonus << std::endl;
}
private:
// 派生类新增的成员变量
double m_bonus;
};
int main() {
Employee emp("Alice", 1001, 8000.0);
emp.work(); // Alice (ID: 1001) is working.
emp.showInfo(); // Name: Alice, ID: 1001, Salary: 8000
std::cout << "---------------------" << std::endl;
Manager mgr("Bob", 2001, 15000.0, 5000.0);
mgr.work(); // Bob (ID: 2001) is working. (继承自Employee)
mgr.manageTeam(); // Bob is managing the team. (Manager自己的)
mgr.showInfo(); // 调用的是Manager重写后的版本
// Name: Bob, ID: 2001, Salary: 15000
// Bonus: 5000
return 0;
}

2.3.2 继承方式

公有,保护,私有三种方式。继承方式决定了基类中的成员派生类中的访问权限。继承方式是为了限制“外部”对“基类部分”的访问,而不是限制派生类内部对基类成员的访问。总之,派生类对基类的访问权限取决于基类和继承方式的最小权限。只有两个都是public时外部才能访问。

无论哪种继承方式,基类的private成员永远无法被派生类直接访问。它们虽然被继承了(存在于派生类对象中),但对派生类来说是“不可见”的。派生类只能通过基类提供的publicprotected接口来间接访问它们。

2.3.3 继承中的构造/析构函数

构造函数和析构函数不能被继承,但是在创建派生类对象时,基类的构造函数会自动被调用。

构造函数的调用顺序:先调用基类的构造函数,再调用派生类自己的构造函数。

// Manager的构造函数
Manager(std::string name, int id, double salary, double bonus)
: Employee(name, id, salary), // 在初始化列表中调用基类构造函数
m_bonus(bonus) { // 初始化派生类自己的成员
// 函数体
}

析构函数的调用顺序相反。

2.3.4 继承的内存布局

派生类对象包含了基类的所有非静态成员变量,以及派生类自己新增的非静态成员变量。这些成员在内存中通常是连续存放的,基类的部分在前,派生类的部分在后。

成员函数(包括虚函数)并不存储在每个对象中。它们存储在代码段。每个对象中只存储一个指向虚函数表的指针(如果类有虚函数),通过这个指针来找到正确的函数版本。

2.3.5 继承中的静态成员

无论继承出多少个派生类,整个继承体系中只有一个静态成员的实例

  • 静态成员变量:被所有基类和派生类的对象共享。
  • 静态成员函数:没有this指针,只能访问静态成员。它同样被继承,但无法被重写为虚函数(因为虚函数依赖于this指针和虚表)。

静态成员函数可以通过基类或者派生类的作用域来访问。

http://www.jsqmd.com/news/1105983/

相关文章:

  • AI 辅助:前端工程化效率:快不是少检查,而是少返工
  • Python在AI开发中的核心优势与实战技巧
  • 变分量子本征求解器(VQE)原理与NISQ设备应用
  • 深度学习Pipeline与Baseline构建指南
  • 【6.20】射频\+FPGA\+Verilog\+仪器自动化 完整知识链路复盘
  • 智能体时代,软件工程的本质
  • 现在系统运行基本上正常,较少遇到问题了
  • 采齿背后的能量闭包原理
  • 截屏、OCR、翻译、录屏全打包?这款开源软件,一个快捷键搞定所有!
  • OpenHarmony 英语学习 App 实战:从 0 到 1 搭建中小学生英语学习应用
  • 工程化赋能传统业务工作流:先找重复劳动,不要先找服务
  • 大模型评测与AI产品质量保障:第7篇 机器学习的三种学习范式
  • SQL实战:测试必会的增删改查,从入门到熟练
  • SpringBoot 自动配置原理
  • 记忆排列题目分析
  • 第93题 IGBT模块陶瓷基板(AlN/Al₂O₃/Si₃N₄)金属化
  • C++ PDF解析渲染库Poppler全方位实战:场景、库对比、CMake集成、可运行代码
  • 死磕信号量实现读者-写者:我被自己写的代码坑惨了
  • 市县级全域旅游智慧导览电子地图制作实操(三)AI+人工生成全域手绘地图
  • Xinference开源大模型本地部署实战指南
  • 工业级条码扫描模块与PIC32MZ嵌入式方案解析
  • 3分钟掌握Illustrator智能填充:Fillinger脚本让你的设计效率翻倍
  • 网络流量分类技术:从机器学习到硬件优化实践
  • UABEA:重新定义Unity资源编辑的跨平台革命
  • 迅雷网盘在线解析:高速直链下载的方法
  • 目标检测分类部分损失函数:BCE → Focal Loss → VFL → MAL 的演进
  • okbiye 毕业论文 AI 写作实操指南|界面全功能拆解,一站式搞定学位论文撰写
  • UE5快捷键速查
  • 主流VST头显视觉性能对比:Vision Pro、Quest 3与Quest Pro评测
  • 大厂高频面试题:手机号加密存储后,如何快速按尾号查询?