C++的特点
C++ 完全支持面向对象的程序设计,包括面向对象开发的四大特性:
- 封装(Encapsulation)
封装是将数据和方法组合在一起,对外部隐藏实现细节,只公开对外提供的接口。这样可以提高安全性、可靠性和灵活性。
- 继承(Inheritance)
继承是从已有类中派生出新类,新类具有已有类的属性和方法,并且可以扩展或修改这些属性和方法。这样可以提高代码的复用性和可扩展性。
- 多态(Polymorphism)
多态是指同一种操作作用于不同的对象,可以有不同的解释和实现。它可以通过接口或继承实现,可以提高代码的灵活性和可读性。
- 抽象(Abstraction)
抽象是从具体的实例中提取共同的特征,形成抽象类或接口,以便于代码的复用和扩展。抽象类和接口可以让程序员专注于高层次的设计和业务逻辑,而不必关注底层的实现细节。
C++基础入门
Linux系统安装
如果您使用的是 Linux 或 UNIX,请在命令行使用下面的命令来检查您的系统上是否安装了 GCC:
$ g++ -v
程序 g++ 是将 gcc 默认语言设为 C++ 的一个特殊的版本,链接时它自动使用 C++ 标准库而不用 C 标准库。
最简单的编译方式:
$ g++ helloworld.cpp
由于命令行中未指定可执行程序的文件名,编译器采用默认的 a.out。程序可以这样来运行:
$ ./a.out Hello, world!
通常我们使用 -o 选项指定可执行程序的文件名,以下实例生成一个 helloworld 的可执行文件:
$ g++ helloworld.cpp -o helloworld
执行 helloworld:
$ ./helloworld Hello, world!
如果是多个 C++ 代码文件,如 runoob1.cpp、runoob2.cpp,编译命令如下:
$ g++ runoob1.cpp runoob2.cpp -o runoob
简单C++程序
// HelloWorld.cpp示例代码 #include <iostream> using namespace std; int main() { cout << "HelloWorld" << endl; return 0; }

头文件
首先,跟C语言一样,C++的源码文件前面一般都会包含头文件的预处理语句:
#include <iostream>
C++的头文件的功能、预处理原理都与C语言无异,下面罗列它们不同与联系:
- C++的标准头文件无需后缀。
- C++可以接收C语言风格后缀的头文件(如#include ),但如有可能,要优先使用C++版本的头文件(如#include ),两者的内容基本是一样的,但后者中的标识符在标准名字空间 std 中均有声明(除了宏之外)。
- C++也接收新风格后缀(如*.hpp)。
#include <iostream> c++标准头文件 #include <cmath> C语言的头文件变成C++使用的版本头文件 在标准名字空间做了声明的改进版math.h #include <unistd.h> 无cunistd版头文件也是 C语言常见的命名 #include <head.hpp> *.hpp后缀头文件
名字空间
using namespace std;
上述语句是C语言没有的,其含义是使用名字空间std中的标识符。这里的名字空间是C++引入的一个新概念。名字空间本质上是自定义的作用域,目的是尽可能防止符号命名冲突。
在 C++ 中,`using namespace std;` 是一个常见的语句,它的作用是将标准命名空间(`std`)中的所有标识符引入到当前的作用域中。
C++ 标准库中的所有类、函数、对象和模板(如 `cout`、`cin`、`string`、`vector` 等)都定义在 `std` 命名空间内,这是为了避免命名冲突(比如防止用户自定义的函数与标准库函数重名)。
如果不使用 `using namespace std;`,要使用标准库中的内容就需要在前面加上 `std::` 前缀,例如:
std::cout << "Hello World" << std::endl; std::string str = "example";
而使用 `using namespace std;` 后,就可以直接使用这些标识符,无需再添加 `std::` 前缀:
cout << "Hello World" << endl; string str = "example";
需要注意的是,在大型项目或头文件中,不建议使用 `using namespace std;`,因为这可能导致命名冲突。更推荐的做法是:
-
直接使用 `std::` 前缀
-
只引入需要的特定标识符,如 `using std::cout;`
`::` 是 C++ 中的作用域解析运算符,主要有以下几种作用:这种语法之所以被视为「静态成员的初始化方式」
作用域解析符::定义的成员函数,仍然属于子类的 "内部
- **访问命名空间中的成员**
当需要使用某个命名空间(如标准库的 `std`)中的标识符时,可以用 `::` 来指定:
std::cout << "Hello"; 访问 std 命名空间中的 cout
- **访问类的静态成员或嵌套类型**
可以直接通过类名加 `::` 访问类的静态成员,无需实例化对象:
class MyClass { public: static int num; }; int MyClass::num = 10; // 定义类的静态成员
- **在类外定义成员函数**
当在类的外部实现成员函数时,需要用 `::` 指明所属的类:
class MyClass { public: void func(); // 声明 }; void MyClass::func() { // 定义,通过 :: 关联到 MyClass // 函数体 }
- **全局作用域**
当局部变量与全局变量同名时,可用 `::` 访问全局变量:
int x = 10; // 全局变量 int main() { int x = 20; // 局部变量 cout << x; // 输出局部变量 20 cout << ::x; // 输出全局变量 10 }
简单来说,`::` 的核心作用是明确指定标识符的作用域,避免命名冲突。
声明
C++ 中名字空间(namespace)的声明位置规则可总结为:
允许声明的位置
-
全局作用域(所有函数、类、结构体外部)
-
其他名字空间内部(支持嵌套声明)
-
同一作用域中可多次拆分声明(最终会合并为一个名字空间)
禁止声明的位置
-
函数内部
-
类或结构体内部
-
任何代码块内部(如 if、for 等语句块)
核心特性
名字空间本质是全局作用域的扩展,只能在全局作用域或其他名字空间中声明,不能在局部作用域中声明,以此保证其能实现跨作用域的标识符隔离与命名冲突避免功能。
标准输入输出流
cout << "HelloWorld" << endl;
标准流对象
所谓的标准流对象,指的是cout、cin和cerr。
所谓对象,本质上就是C语言语境中的变量,只不过在面向对象的语境中,这些变量都是自带函数的,它们是名副其实的超级变量,因此为了与C语言的普通变量加以区分,在面向对象的编程语言中,通常将它们称为对象。
cout: 标准输出流对象,典型用法如下: cout << 100; // 输出整型数据 cout << 3.14; // 输出浮点型数据 cout << "abcd";// 输出字符串数据 cin: 标准输入流对象,典型用法如下: int a; double f; string s; cin >> a; // 从键盘接收一个整型数据放入变量a中 cin >> f; // 从键盘接收一个浮点型数据放入变量f中 cin >> s; // 从键盘接收一个字符串放入变量s中
可以明显看到:
使用流对象的优势在于,不需要关心操作数据的类型,流对象会自动识别不同的数据类型,也可以一次性快速处理,例如上述代码也可写成:
int a; double f; string s; 一次性输出多种不同类型的数据 cout << 100 << 3.14 << "abcd"; 一次性输如多种不同类型的数据 cin >> a >> f >> s;
endl 的作用有两个:
- 输出一个换行符(相当于 \n)
- 刷新输出缓冲区:强制将输出缓冲区中的内容立即显示到屏幕上(或写入文件),确保数据即时可见。
string类的函数
在 C++ 中,`string` 是标准库提供的字符串类,定义在 `` 头文件中,封装了丰富的字符串操作函数。以下是常用的 `string` 成员函数及作用:
以下是上述 `string` 函数的代码运行结果整理(基于代码示例的预期输出):
- 构造函数
string s1; 空字符串(输出为空) string s2("hello"); "hello" string s3(5, 'a'); "aaaaa" string s4(s2); "hello"(与s2相同)
- 长度与容量操作
string s = "hello"; cout << s.length(); 输出:5 cout << s.empty(); 输出:0(false,非空) s.resize(8, 'x'); cout << s; 输出:"helloxxx"(长度调整为8,补3个'x')
- 字符串访问
string s = "hello"; cout << s[0]; 输出:h cout << s.at(1); 输出:e cout << s.front(); 输出:h cout << s.back(); 输出:o
- 字符串修改
string s = "abc"; s.append("def"); s = "abcdef" → 输出:abcdef s.push_back('g'); s = "abcdefg" → 输出:abcdefg s.erase(3, 2); 从索引3删2个字符("de")→ 输出:abcfg s.replace(1, 2, "xy"); 替换索引1开始的2个字符 → 输出:axyfg
- 字符串比较
string s1 = "apple", s2 = "banana"; cout << s1.compare(s2); 输出:-1(或其他负数,因"apple"字典序更小) cout << (s1 < s2); 输出:1(true,"apple" < "banana") 如果 s1 小于 s2(按字典序),返回负数(通常是 -1); 如果 s1 等于 s2,返回0; 如果 s1 大于 s2(按字典序),返回正数(通常是 1)。
- 字符串查找
string s = "hello world"; cout << s.find("lo"); 输出:3("lo"从索引3开始) cout << s.rfind("l"); 输出:9(最后一个'l'在"world"的索引9) cout << s.find("x"); 输出:18446744073709551615(即string::npos,未找到)
- 子字符串提取
string s = "hello world"; string sub = s.substr(6, 5); cout << sub; 输出:world(从索引6取5个字符)
- 数值转换
string s = "123"; int num = stoi(s); cout << nu
C++ 技术文章大纲
C++ 的特点
- 面向对象编程的四大特性
- 封装(Encapsulation):数据与方法的组合,隐藏实现细节,提高安全性、可靠性和灵活性。
- 继承(Inheritance):派生新类,复用已有类属性和方法,增强代码复用性和可扩展性。
- 多态(Polymorphism):同一操作作用于不同对象时产生不同行为,提升代码灵活性和可读性。
- 抽象(Abstraction):提取共同特征形成抽象类或接口,便于复用和扩展代码。
C++ 基础入门
-
Linux 系统安装与编译
- 检查 GCC 安装:
g++ -v
- 编译简单程序:
g++ helloworld.cpp -o helloworld
- 运行程序:
./helloworld
- 多文件编译:
g++ file1.cpp file2.cpp -o output
- 检查 GCC 安装:
-
简单 C++ 程序示例
cpp
#include <iostream>
using namespace std;
int main() {
cout << "HelloWorld" << endl;
return 0;
}
头文件与名字空间
-
头文件
- C++ 标准头文件无需后缀(如
<iostream>
)。 - 优先使用 C++ 版本的头文件(如
<cmath>
替代<math.h>
)。 - 支持新风格后缀(如
.hpp
)。
- C++ 标准头文件无需后缀(如
-
名字空间
- 使用
using namespace std;
引入标准库标识符。 - 避免在大型项目或头文件中使用,防止命名冲突。
- 替代方案:直接使用
std::
前缀或引入特定标识符(如using std::cout;
)。
- 使用
作用域解析运算符(::)
- 功能
- 访问命名空间成员(如
std::cout
)。 - 访问类的静态成员或嵌套类型。
- 在类外定义成员函数(如
void MyClass::func()
)。 - 访问全局变量(如
::x
)。
- 访问命名空间成员(如
标准输入输出流
-
标准流对象
cout
:标准输出流,自动识别数据类型(如cout << 100 << "text";
)。cin
:标准输入流,支持多类型输入(如cin >> a >> b;
)。cerr
:标准错误流。
-
endl
的作用- 输出换行符(
\n
)。 - 刷新输出缓冲区,确保数据即时显示。
- 输出换行符(
string
类常用函数
-
构造函数
string s1;
:空字符串。string s2("hello");
:初始化字符串。string s3(5, 'a');
:重复字符构造("aaaaa"
)。
-
长度与容量操作
s.length()
:返回字符串长度。s.empty()
:检查是否为空。s.resize(8, 'x');
:调整长度并填充字符。
-
字符串访问
s[0]
:通过索引访问字符。s.at(1)
:安全索引访问。s.front()
和s.back()
:访问首尾字符。
-
字符串修改
s.append("def");
:追加字符串。s.push_back('g');
:追加单个字符。s.erase(3, 2);
:删除子串。s.replace(1, 2, "xy");
:替换子串。
-
字符串比较
s1.compare(s2)
:返回字典序比较结果。- 直接使用运算符(如
s1 < s2
)。
-
字符串查找
s.find("lo")
:返回首次出现的位置。s.rfind("l")
:返回末次出现的位置。- 未找到时返回
string::npos
。
m; 输出:123(字符串转int) string str = to_string(3.14); cout << str; 输出:3.14(double转字符串)
以上结果基于标准 C++ 编译器(如 GCC、Clang)的正常执行,不同环境下输出一致(`string::npos` 的具体数值可能因系统而异,但均表示"未找到")。