C++ 命名空间与模板
·
文章目录
C++ 命名空间与模板
解决命名冲突 + 泛型编程利器。
一、命名空间(namespace)
1.1 为什么需要命名空间
随着项目规模增大,命名冲突几乎不可避免:
- 自己写的
strcat()会覆盖标准库的strcat() - 两个第三方库可能都定义了
string类 - 多人协作时函数名、类名容易撞车
命名空间的本质: 给标识符加一个"姓氏",把全局作用域拆成独立的小房间,同名标识符在不同房间里互不干扰。
namespace 名称 {
// 声明
}
在命名空间中定义的任何东西都局限于该命名空间内。
1.2 基础用法
#include <iostream>
#include <iomanip>
using namespace std;
namespace Onespace { // 第一命名空间
void print() {
cout << "执行Onespace名字空间的print()函数" << endl;
}
}
namespace Twospace { // 第二命名空间
void print() {
cout << "执行Twospace名字空间的print()函数" << endl;
}
}
using namespace Twospace; // 引入 Twospace,使其成员可直接使用
int main() {
Onespace::print(); // 通过 :: 限定访问 Onespace
Twospace::print(); // 通过 :: 限定访问 Twospace(不用 using 也行)
print(); // 由于 using 了 Twospace,直接调用
print();
return 0;
}
::叫作用域解析运算符,命名空间::成员,就像一个门牌号。
运行结果

1.3 嵌套命名空间
命名空间可以嵌套,像文件夹套文件夹:
namespace 命名空间名称1 {
// 代码声明
namespace 命名空间名称2 {
// 代码声明
}
}
示例:
#include <iostream>
#include <iomanip>
using namespace std;
namespace Onespace {
void print() {
cout << "执行Onespace名字空间的print()函数" << endl;
}
namespace Twospace { // 嵌套在 Onespace 内部
void print() {
cout << "执行Twospace名字空间的print()函数" << endl;
}
}
}
using namespace Onespace::Twospace; // 只引入嵌套的 Twospace
int main() {
print(); // 调用 Onespace::Twospace::print()
return 0;
}
访问嵌套成员:
Onespace::Twospace::print(),用::逐层穿透。
运行结果

1.4 using 指令小结
| 写法 | 效果 | 推荐度 |
|---|---|---|
using namespace std; |
整个命名空间全部引入 | 学习时方便,大项目慎用 |
using std::cout; |
只引入单个成员 | 精准,推荐 |
std::cout |
不用 using,每次写全名 | 最安全 |
二、模板(Template)
泛型编程的核心:写一份代码,适配多种类型。模板是创建泛型类或函数的蓝图。
2.1 函数模板
template <typename T>
返回类型 函数名(参数列表) {
// 函数主体
}
T 是类型占位符,编译时会被实际类型替换。
示例:求两数最大值
#include <iostream>
#include <string>
using namespace std;
template <typename T>
inline T const& MaxFunc(T const& a, T const& b) {
return a > b ? a : b;
}
int main() {
int i = 90, j = 100;
cout << "int类型MaxFunc(i,j)=" << MaxFunc(i, j) << endl;
double f1 = 10.1, f2 = 20.115;
cout << "double类型MaxFunc(i,j)=" << MaxFunc(f1, f2) << endl;
string s1 = "helloworld", s2 = "goodbye";
cout << "string类型MaxFunc(i,j)=" << MaxFunc(s1, s2) << endl;
return 0;
}
inline建议编译器内联展开,省去函数调用开销。这里用const&避免了不必要的拷贝。
运行结果

2.2 类模板
template <class T>
class 类名 {
// 使用 T 作为类型占位符
};
多个泛型参数用逗号分隔:template <class T1, class T2>
示例:比较两个数
#include <iostream>
#include <string>
using namespace std;
template <typename T>
class CompareSS {
public:
CompareSS(T a, T b) {
x = a;
y = b;
}
T maxfunc() {
return (x > y ? x : y);
}
private:
T x, y; // 成员变量也使用模板类型
};
int main() {
CompareSS<int> obj1(30, 90);
cout << "int最大值为:" << obj1.maxfunc() << endl;
CompareSS<double> obj2(30.12346, 90.123);
cout << "double最大值为:" << obj2.maxfunc() << endl;
return 0;
}
实例化时必须指定类型:
CompareSS<int>、CompareSS<double>。编译器会为每种类型生成一份独立的类代码。
运行结果

三、核心要点总结
| 知识点 | 一句话 |
|---|---|
| 命名空间 | 给标识符分区,避免同名冲突;用 :: 访问 |
| 嵌套命名空间 | 命名空间里套命名空间,A::B::func() 逐层穿透 |
| using 指令 | 偷懒写法,大项目建议 using 单个成员 或写全名 |
| 函数模板 | template <typename T> 让函数适配任意类型 |
| 类模板 | template <class T> 让类适配任意类型,实例化时指定 |
记忆口诀
- 命名空间 = 姓氏:王家::张三 和 李家::张三 不是同一个人
- 模板 = 模具:一套模具,灌什么材料出什么产品
typename和class在模板参数里基本等价,混用看习惯
更多推荐

所有评论(0)