C++概述 (一)
一,C与C++区别
- c语言是面向过程的编程语言,核心是函数和数据结构,专注于通过步骤化的代码解决问题
- c++是面向对象的编程语言,核心是类和对象,通过封装,继承,多态实现代码复用和模块化。
- c语言仅支持面向过程,需要按照“函数+数据”的思路来拆解任务,c++即支持面向对象,也可以支持面向过程,除包含的类、封装、继承、多态之外,还新增了引用、模板、STL标准库等功能,所以c++可以适合更复杂的项目。
- 在c语言中通过malloc和free进行堆内存管理,c++除此之外新增了new和delete,其可以自动完成对象的构造与释放,更加安全高效。
- c语言更适合底层代码开发,代码轻量、执行效率高;c++适合大型复杂项目,能兼顾效率与开发的灵活性。
二,C++三大特性
C++是一种面向对象的编程,面向对象是一种以对象为中心的程序设计范型。也可以说是一套概念和想法,是一种用计算机程序来描述实际问题的思路。是一种新的思维和编程方法。
程序 = 对象 + 消息
有一个经典问题:如何把大象塞进冰箱?
利用面向对象编程思想去理解该问题。
为了把大象塞进冰箱,需要三个动作。 每个动作都有一个主体。这个主体我们理解为对象。 冰箱,把门打开(冰箱:开门) 冰箱,把大象让我塞进去(冰箱:被塞进大象) 冰箱,把门关上(冰箱:关门)
C++面向对象的优点:
- 封装:降低代码的耦合性,提升安全性。
- 继承:减少重复代码,实现功能扩展。
- 多态:统一接口,适配不同实现。
- 模块化:便于后续团队协作和维护。
C++面向对象三大特性:
- 封装:将类的属性和方法整合在一起,对外隐藏实现细节,仅通过公开接口与外部交互。
- 继承:让子类能够自动获取父类的属性和方法。同时子类又可以新增或重写方法以实现功能扩展。
- 多态:通过虚函数实现“同一接口,不同行为”。父类的指针或引用指向子类对象时,自动决定函数调用。(运行时多态)
封装(encapsulation)
1.把对象的属性和功能结合成一个独立的系统单位。
2.尽可能隐蔽对象的内部细节。对外形成一道屏障,只保留有限的对外接口使之与外部发生联系。
封装在现实中的例子,人们使用录音机,只要知道键的功能即可(放音、录音、停止、倒带等),不需要知道这些功能是如何实现的,也不需要知道其内部电路或构造。
继承( inheritance)
1.继承对于软件代码的重复利用有着重要意义,是面向对象技术能够提高软件开发效率的重要原因之一。
2.定义:如果类的对象A拥另一个类B的全部属性与服务,称作类A对类B的继承。
多态( polymorphism )
多态是指在一般类中定义的属性或行为,被特殊类继承之后,可以具有不同的数据类型或表现出不同的行为。这使得同一个属性或行为在一般类及其各个特殊类中具有不同的语义。
* 例如:数的加法->实数的加法 ->复数的加法
C++语言支持两种多态性
编译时多态性和运行时多态性
C++中,编译时多态是通过重载实现的,而运行时多态是通过虚函数实现的。
三,输入与输出
发展历程:
1、1983 年 C++ 诞生,既要编程简单、正确可靠,又要运行高效、可移植。1979年Bell实验室,开始从事将C改良为带类的C(C with classes)的工作 。1967 - Simula 是最早的面向对象程序设计语言,引入了类、对象、继承 。
2、1993 年 引入RTTL 命名空间
3、1997 年 美国国家标准
4、1998 年 国际标准
5、2011 年 修正版 c++11
C -->C++ -->Java
特点:
1、c++ 完全支持c语言,c语言属于c++的子集;
2、c++ 完全支持面向对象编程, 也支持面向过程编程 也支持泛型编程;
3、c++ 的关键字扩增到63个
编程环境:
1、代码文件: xxx.cpp 后缀结尾
2、编译器: g++ xxx.cpp
g++编译流程:预处理->编译->汇编->链接
(1) g++ -E main.cpp // 查看一个文件的预处理过程 只显示预处理,不产生文件
(2) g++ -E main.cpp -o main.i 将预处理信息定位至main.i文件中
(3) g++ -s main.i -o main.s 编译到汇编语言,不进行汇编和链接,即只激活预处理和编译,生成汇编语言
(4) g++ -c main.s -o main.o 编译、汇编到目标代码,不进行链接,即生成目标文件
(5) g++ main.o -o main 生成链接文件
(6) ./main 执行
什么情况下会刷新输出缓冲区呢,有如下五种情况:
1.程序正常结束。作为main返回工作的一部分,将清空所有的输出缓冲区。
#include <iostream>int main() {// 这段文本可能不会立即显示std::cout << "Hello, World!"; // 当 main 函数返回时,缓冲区被刷新,文本内容显示出来。return 0;
}
说明:
在这个例子中,"Hello, World!" 被写入 `cout` 的缓冲区。因为程序马上就结束了,所以可能感觉不到延迟。但如果程序在 `return 0;` 之前有耗时很长的操作,你就会发现这行文本直到程序即将退出时才显示。
2.在一些不确定的时候,缓冲区可能已经满了,在这种情况下,缓冲区将会在写下一个值之前刷新。
#include <iostream>int main() {// 循环输出大量的字符来尝试填满缓冲区for (int i = 0; i < 10000; ++i) {std::cout << 'X';}std::cout << "Loop finished." << std::endl;return 0;
}
说明:
当运行这段代码时,大量的 'X' 字符会被写入缓冲区。由于缓冲区大小是有限的(例如4096字节),当它被填满时,内容就会被刷新到屏幕上,然后继续填充。因此,你可能会看到几批 'X' 字符突然出现,而不是平滑地逐个显示。
3.用操纵符显示地刷新缓冲区,如用endl、‘\n’。
#include <iostream>
#include <thread>
#include <chrono>int main() {std::cout << "Using '\\n': ";for (int i = 0; i < 5; ++i) {std::cout << i << " ";// 使用 \n 不会立即刷新,输出可能会延迟std::this_thread::sleep_for(std::chrono::seconds(1));}std::cout << "\n"; // 最后换行std::cout << "Using endl: ";for (int i = 0; i < 5; ++i) {std::cout << i << " " << std::endl; // 使用 endl 会立即刷新std::this_thread::sleep_for(std::chrono::seconds(1));}std::cout << "Using flush: ";for (int i = 0; i < 5; ++i) {std::cout << i << " " << std::flush; // 使用 flush 会立即刷新std::this_thread::sleep_for(std::chrono::seconds(1));}std::cout << std::endl;return 0;
}
说明:
第一个循环使用 \n,会发现程序暂停了5秒后,数字 "0 1 2 3 4" 一次性全部显示出来。
第二个和第三个循环分别使用 endl 和 flush,会看到数字每隔一秒钟出现一个,因为每次输出后都强制刷新了缓冲区。
4.在每次输出操作执行完毕后,用unitbuf、nounitbuf 操纵符设置流的内部状态,从而清空缓冲区。
#include <iostream>
#include <thread>
#include <chrono>int main() {// 设置 cout 为每次输出后都刷新std::cout << std::unitbuf; std::cout << "unitbuf is on. ";for (int i = 0; i < 5; ++i) {// 这里的输出会立即显示,即使没有使用 endl 或 flushstd::cout << i << " "; std::this_thread::sleep_for(std::chrono::seconds(1));}// 恢复到正常的缓冲模式std::cout << std::nounitbuf;std::cout << "\nnounitbuf is on. Output will be buffered again." << std::endl;return 0;
}
说明:在设置了 std::unitbuf 之后,每一次对 std::cout 的输出操作(如 std::cout << i << " ";)都会紧跟着一次缓冲区的刷新,因此数字会每隔一秒出现一个。
5.可将输出流与输入流关联起来,在读输入流时将刷新其关联的输出缓冲区。(tie)
#include <iostream>
#include <string>int main() {std::string name;// "Please enter your name: " 被写入缓冲区,但没有换行符或 endlstd::cout << "Please enter your name: "; // 当程序试图从 cin 读取数据时,它会首先刷新 cout 的缓冲区// 这样可以确保提示信息在用户输入之前显示出来std::cin >> name;std::cout << "Hello, " << name << "!" << std::endl;return 0;
}
说明:
在这个例子中,提示信息 "Please enter your name: " 后面没有 std::endl。但因为 std::cout 默认关联到了 std::cin,所以在执行 std::cin >> name; 之前,std::cout 的缓冲区会被刷新,从而保证用户能看到提示信息。