举爪爪打招呼

很高兴你点开这篇文章✨

这里会持续更新我喜欢的内容,关注我,一起慢慢变好呀

👍 点赞 ⭐ 收藏 💬 评论


前言

C++ 命名空间与输入输出:从“名字冲突”到“域隔离”

  • 你写的第一个 C++ 程序可能和我一样:cout << “hello world” << endl;
  • 但为什么需要 using namespace std?
  • namespace 到底解决了什么问题?

🐾 这篇文章带你用代码理解 C++ 的域与命名空间。

🐶 🐾 ✨ 🐾 🐶


一、C++的第一个程序

C++兼容C语言绝大多数的语法,所以C语言实现的 hello world 依旧可以运行,C++中需要把定义文件代码后缀改为.cpp,vs编译器看到是.cpp就会调用C++编译器编译,linux下要用g++编译,不再是gcc

🐾 C :

//test.cpp
#include<stdio.h>
int main()
{
	printf("hello world\n");
	return 0;
}

当然C++有⼀套⾃⼰的输⼊输出,严格说C++版本的hello world应该是这样写的。

🐾 C++ :

//test.cpp
#include<iostream>
using namespace std;
int main()
{
	cout<<"hello world"<<endl;
	return 0;
}

🐶 🐾 ✨ 🐾 🐶


二、从一个“冲突”问题开始

C++ 允许我们定义变量、函数、结构体。
但项目一大,很容易出现同名冲突。

比如:

#include <stdlib.h>
int rand = 10;   //  编译错误:rand 已经是函数名
  • 因为 stdlib.h 里已经有一个 rand() 函数。
  • C++ 中,全局空间是共用的,同名就会冲突。

三、域:我们可以理解为C++ 的“隔离墙”

🐾 C++ 中的域分为四类:

域类型 作用 影响生命周期
局部域 { } 内
全局域 所有函数外部
命名空间域 namespace 定义
类域 class / struct 内部

🐾 域的核心作用:

  • 告诉编译器“去哪里找这个名字”。

  • 编译器默认查找规则(不指定域时):

    • 先局部域,全局域
int a = 11;   // 全局

int main() 
{
    int a = 1;      	  // 局部
    printf("%d\n", a);    // 1(局部优先)
    printf("%d\n", ::a);  // 11(:: 强制全局)
    return 0;
}

:: 叫做 域作用限定符

  • 有这个操作符的情况下,系统的搜索逻辑就是访问全局优先
  • 左边不写 = 全局,左边写名字 = 指定命名空间/类(如Date::a)

四、namespace:给名字一个“家”

🐾 基本用法

namespace CC {
    int rand = 10;
    int Add(int left, int right) {
        return left + right;
    }
}

🐾 访问时:

printf("%d\n", CC::rand);   // 10
printf("%d\n", CC::Add(2, 3));

🐾 为什么 rand 不冲突了?

  • 全局 rand 是函数
  • CC::rand 是变量
    • 它们在不同的命名空间域,编译器可以区分。

五、命名空间可以嵌套

namespace CC 
{
    namespace dy 
    {
        int rand = 1;
    }
    namespace qe {
        int rand = 2;
    }
}

printf("%d\n", CC::dy::rand);   // 1
printf("%d\n", CC::qe::rand);   // 2

🐾 适合大型项目的模块分层(例如 公司::项目::模块)


六、using namespace std 到底在干嘛?他能够自动识别类型!

🐾C++ 标准库所有内容都在 std 命名空间中:

#include <iostream>

//  如果没有 using 或 std::cout << "hello";  就会错误

//  方法1:全量打开
using namespace std;

//  方法2:部分展开(推荐)
using std::cout;
using std::endl;

//  方法3:显式使用(最安全)
std::cout << i << std::endl;

不推荐随便 using namespace std 的原因

  • 一旦打开,你写的 vector、sort 就可能与标准库冲突。

  • 公司/开源项目一般写 std::cout,或在 .cpp 局部展开。


七、C++ vs C :输入输出

功能 C C++
输出 printf std::cout <<
输入 scanf std::cin >>
换行 \n std::endl 或 “\n”
类型 必须用格式化符 自动识别类型
安全 较低(格式错误) 较高(编译时检查,但不是绝对)

🐾 示例

double s = 2.22222;
printf("%.2f", s);         // 2.22
std::cout << s;            // 2.22222(不截断)

std::cin >> i >> s;        // 类似 scanf
std::cout << "i=" << i;

🐾 cout / cin 优势:

  • 无需记忆 %d %f %p
  • 可连续链式输出
  • 性能略低于 printf

🐶 🐾 ✨ 🐾 🐶


八、本文全部代码

#define _CRT_SECURE_NO_WARNINGS 1


////初学C++的第一个代码,它的头文件通常不带.h.如<iostream.h>是错的
//#include<iostream>

//using namespace std;				//std类似一个工具箱,用这句代码意思就是工具箱打开,里面的工具随你用
//int main()							//cout(输出),endl(换行),cin(输入),string(字符串),vector、map(容器),sort(算法)...都是std里的工具
//{
//	cout << "hello world" << endl;	//cout->printf;endl->换行符(\n)
//	return 0;
//}

//////////////////////////////////////////////////////////////////////////////////
//  C++中域有函数局部域,全局域,命名空间域,类域
// //域影响的是编译时语法查找一个变量/函数/类型出处(声明或定义)的逻辑,当有了域隔离,名字冲突就解决了
// //局部域和全局域除了会影响编译查找逻辑,还会影响变量的生命周期,命名空间域和类域不影响变量生命周期
//接下来了解namespace
// 
//#include<iostream>
//#include<stdlib.h>
//namespace CC
//{
//	int rand = 10;					//rand 是个函数名,<stdlib.h>里也一个rand;
//									//当程序出现里另一个rand 时(也就是这里的rand)就会报错,用namespace就可以加以区分了
//									//放在cout里rand会被当成函数指针,输出的是一串地址数字
//	int Add(int left, int right)
//	{
//		return left + right;
//	}
//	struct Node
//	{
//		struct Node* next;
//		int val;
//	};
//}
//int a = 11;			//这里出现两个a,系统会要那个呢?
//					//系统的搜索逻辑在没有指定域的情况下就是:先局部,再全局;所以第一个printf输出的值是1
//int main()
//{
//	int a = 1;
//	printf("%d\n", a);
//	printf("%d\n", ::a);	//::是域作用限定符,有这个操作符的情况下,系统的搜索逻辑就是访问全局优先
//							//::前面如果没有写其他东西就是全局访问,如果有,就是先访问该域(如Date::a)
//
//	printf("%p\n", rand);		//在cout(printf)里,rand是个函数指针,打印出来的是地址数字,所以用%p
//	printf("%d\n", CC::rand);	//用来访问命名空间namespace里的rand,输出结果就是10了
//
//	printf("%p\n", CC::Add);		//这里如果不指定(即访问全局),编译器就会报错,因为Add在局部里
//	printf("%d\n",CC:: Add(2,3));
//
//	return 0;
//}

////////////////////////////////////////////////////////////////////////////////////////////////////
////namespace还可以嵌套
//
//#include<iostream>
//
//namespace CC
//{
//	//
//	namespace dy
//	{
//		int rand = 1;
//		int Add(int left, int right)
//		{
//			return left + right;
//		}
//	}
//	//
//	namespace qe
//	{
//		int rand = 2;
//		int Add(int left, int right)
//		{
//			return left + right;
//		}
//	}
//}
//
//int main()
//{
//	printf("%d\n", CC::dy::rand);//1
//	printf("%d\n", CC::qe::rand);//2
//	return 0;
//}

////////////////////////////////////////////////////////////////////////////////////////////////
//自动识别类型

#include<iostream>
//using namespace std;
//using std::cout;
//using std::endl;
int main()
{
	int i = 1;
	

	double s = 2.22222;
	//cout <<i << endl;		//这里如果不加std::,他就会报错,因为cout和endl是头文件<iostream>定义的全局对象
							//下面的cin也用不了
	std::cout << i << std::endl;;//要么在文件开头写上 using namespace std
								//他也可以部分展开:using std::cout;
								//					using std::endl;
								//为了避免我们定义的东西和库里面的冲突

	std::cout << "nihao" << " " << "ma"<<std::endl;//会自动识别出空格符

	printf("%.2f", s);		//保留两位小数

	std::cin >> i >> s;		//类似scanf
	std::cout << "i=" << i << std::endl;
	std::cout << "s=" << s << std::endl;
	return 0;
}

🐶 🐾 ✨ 🐾 🐶


举爪爪求关注

小狗举爪爪求关注啦!🥺

你的关注,就是我更新的最大动力~

👍 点赞 ⭐ 收藏 💬 评论

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐