• 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中。一般声明和实现都放在头文件里否则会报错

  • 相关阅读:
    c++11 可变参数模板类
    c++11 可变参数模板函数
    c++11 函数模板的默认模板参数
    c++11 模板的别名
    超声波模块SRF05
    Eclipse中快捷键的使用
    移动互联网教育领域或将出现新的风口?
    java Date 和 javascript Date
    linux下安装node.js
    J2EE之初识JSP
  • 原文地址:https://www.cnblogs.com/pupububu/p/14160986.html
Copyright © 2020-2023  润新知