C++ 命名空间 函数重载 内联函数

命名空间

名字冲突:

一般:工程_模块_函数名

作用域:全局作用域,块作用域,文件作用域,文件作用域

1.using namespace XXX

//using namespace XXX
#include <iostream>
using namespace std;
namespace CR {
    //凡是在全局作用域中做的事,命名空间中都可以做
    int g_nVal = 999;
    void Foo()
    {
        cout << "CR::Foo" << endl;
    }
    struct tagTest
    {
        int m_n;
        float m_f;
    };
    typedef void(*PFN)();

}
1.using namespace CR;//开关,把CR命名空间中的名字拉到当前作用域


int main()
{
    {
        using namespace CR  //2.若在这里使用using,则会报错,只能在这块里面使用CR39里面的属性方法。
    }
    g_nVal = 0;  //调试监视的时候,需要使用 CR::g_nVal
    Foo();
    tagTest t;
    t.m_f = 23.1f;
    t.m_n = 2;
    using namespace CR;//前面报错,这行后面,才能找到作命名空间。跟定义变量一样,要使用变量前,先定义变量。
    PFN pfn = Foo;
    pfn();
}



2.使用时 XXX::+()

//xxx::+()
#include <iostream>
using namespace std;
namespace CR {
    //凡是在全局作用域中做的事,命名空间中都可以做
    int g_nVal = 999;
    void Foo()
    {
        cout << "CR::Foo" << endl;
    }
    struct tagTest
    {
        int m_n;
        float m_f;
    };
    typedef void(*PFN)();

}


int main()
{
    
    CR::g_nVal = 0;  
    CR::Foo();
    CR::tagTest t;
    t.m_f = 23.1f;
    t.m_n = 2;
    
    CR::PFN pfn = Foo;
    pfn();
}

3.using XXX::+()

把XXX中的()拉到当前作用域。类似python中的 from xxx import xxxx

注意!如果出现以下场景。

using namespace CR1{
	int g_nVal=9;
}
using namespace CR2{
	int g_nVal=8;
}
int g_nVal=7;//全局作用域
using namespace CR1;
using namespace CR2;

//需要指明使用对象。
int main()
{
	CR1::g_nVal=22;//指明使用CR1中的g_nVal
	::g_nVal=21;//使用全局作用域中的g_nVal
}

命名空间可以拆开写,但都表示同一块命名空间。

4.起别名

//CR代码在上方,可以省略
namespace CR1=CR;
usint namespace CR1;
//CR1的用法跟上面一样。

函数重载

在C语言中,没有函数重载,功能相似的函数,参数不同,C语言中通过前缀或者后缀区分。

如下

int Add(int n1, int n)
{
    return n1 + n;
}
float float_Add(float n1, float n2)
{
    return n1 + n2;
}
float float2_int2_Add(float n1, float n2, int n3, int n4)
{
    return n1 + n2 + n3 + n4;
}

在C++中。

int Add(int n1, int n)
{
    return n1 + n;
}
float Add(float n1, float n2)
{
    return n1 + n2;
}
float Add(float n1, float n2, int n3, int n4)
{
    return n1 + n2 + n3 + n4;
}

函数:返回值,调用约定,函数名,参数列表(参数类型,参数的数量,参数的顺序)

参数不同,构成重载

int Add(int n)
{
    return 0;
}
int Add(int n, int n1)
{
    return 0;
}
int main() {
    Add(1);
    Add(1, 2);

}

参数类型不同,构成重载

int Add(int n)
{
    return 0;
}
int Add(float n)
{
    return 0;
}
int main() {
    Add(1);
    Add(1.4f);

}

参数顺序不同,构成重载

int Add(int n, float r)
{
    return 0;
}
int Add(float, int r)
{
    return 0;
}
int main() {
    Add(1, 2.f);
    Add(1.4f, 2);
}

调用约定不同,不构成重载

int __stdcall Add(int n, float r)
{
    return 0;
}
int __cdecl Add(float g, int r)
{
    return 0;
}
int main() {
    Add(1, 2.f);
    Add(1.4f, 2);
}

返回值类型不同,不构成重载

float Add(int n)
{
    return 0;
}
int Add(float r)
{
    return 0;
}
int main() {
    Add(1);
    Add(1.4f);
}

总结:

构成重载的条件:
1.函数名相同
2.参数列表不同(顺序,类型,个数)
3.返回值和调用约定不考虑

外:

作用域不同,不构成重载

using namespace std;
void Foo(char* p)
{
    cout << p << endl;
}
namespace CR
{
    void Foo(int n)
    {
        cout << n << endl;

    }
    void Test()
    {
        //Foo("Hello")//作用域内部Foo屏蔽了全局作用域中Foo
    }
}
int main()
{
    return 0;
}

名称粉碎

//函数重载的原理:名称粉碎 ?Foo@CR@@YAXMHNPAD@Z
namespace CR {
    void Foo(float f, int n, double dbl, char* p);
  
}

int main()
{
    
    CR::Foo(3.2f, 2, 4.5, nullptr);
    return 0;
}

使用VS2019自带的控制台

C++兼容C的调用约定

C 前缀 _

c++ @

//函数重载的原理:名称粉碎 ?Foo@CR@@YAXMHNPAD@Z
namespace CR {
    void Foo(float f, int n, double dbl, char* p)
    {

    }
}
extern "C" void Test();//告诉编译器,此函数的名称粉碎规则使用C的而不是C++的
//使用extern "C"后无法进行函数重载
extern "C"  void Test1(int n)
{


}
extern "C"  void Test2(int n)
{


}


int main()
{
    Test();
    CR::Foo(3.2f, 2, 4.5, nullptr);
    return 0;
}

二义性,歧义

1.要注意函数的调用过程中,注意参数的完美匹配
void Add(int n)
{

}
void Add(float f)
{

}
int main()
{
    Add(36.5);
    return 0;
}

2.默认参对函数重载有影响
void Add(int n)
{

}
void Add(int n, float f = 3.2f)
{

}
int main()
{
    Add(36.5);
    return 0;
}

内联函数

函数调用
1.参数入栈
2.返回地址入栈
3.保存栈帧
4.分配局部变量空间
5.保存寄存器环境
6.执行函数体
7.还原寄存器
8.释放局部变量空间
9.还原栈帧
10.返回调用点

int Max(int n1, int n2)
{
	return n1 > n2 ? n1 : n2;
}
#define MAX(x,y)(x>y>x:y)  
/*
短函数:体积小 效率低,方便调试  -->时间换空间
宏:体积大 效率高,不方便调试 -->空间换时间
*/
/*
内联函数:既可以像函数一样可以调试,也可以在调用点像宏一样展开.利用inline定义
debug:任何函数都不会展开,release需要开Ob1选项

*/
inline int Max(int n1, int n2)
{
	return n1 > n2 ? n1 : n2;
}
int main(int argc,char * argv[])
{
	
	std::cout << Max(argc, argv[0][2]);
}

VS改内联规则:

inline:建议编译器内联,但是能不能够内联成功,看编译器。

inline int Foo(int n1)
{
	if (n1 == 0)
	{
		return 0;
	}
	return Foo(n1 - 1) + n1;
}
int main(int argc, char* argv[])
{

	std::cout << Foo(argc);
}

如下图,。函数调用了

内联函数不能拆分到头文件和Cpp中。一般声明和实现都放在头文件里否则会报错

原文地址:https://www.cnblogs.com/pupububu/p/14160986.html