04. 命名空间,函数重载,内联

一.命名空间

C语言中为避免冲突,可能采用

项目名_模块名_名字 的形式,缺点是冗长

C语言中作用域:块,局部(函数),文件,全局

C++有采用命名空间

用法1:using namespace MyNamespace;

namespace MyNamespace {
    //可以做所有能在全局作用域中做的事
    int val = 9;//全局
    void f() {

    }
    struct MyStruct {
        int age;
        double score;
    };
}

using namespace MyNamespace;

int main() {   
    val = 100;
    f();
    MyStruct str{ 1,1.1234 };
    return 0;
}

int Foo() {
    val = 100;
    f();
    MyStruct str{ 1,1.1234 };
    return 0;
}

  

如果把using namespace MyNamespace;放在函数内部,则只在该函数内可见。

int main() {   
    using namespace MyNamespace;//把整个命名空间的所有名字导入当前作用域
    val = 100;
    f();
    MyStruct str{ 1,1.1234 };
    return 0;
}

int Foo() {
    //本函数无法使用以下内容,编译出错
    val = 100;
    f();
    MyStruct str{ 1,1.1234 };
    return 0;
}

  

用法2:

int main() {     
    MyNamespace::val = 100;
    MyNamespace::f();
    MyNamespace::MyStruct str{ 1,1.1234 };
    return 0;
}

  

用法3:

using MyNamespace::val;//把MyNamespace的val导入当前作用域
using MyNamespace::f;
using MyNamespace::MyStruct;

int main() {       
    val = 100;
    f();
    MyStruct str{ 1,1.1234 };
    return 0;
}

  

命名空间可以不连续,可以写在多个文件中,例如:

namespace MyNamespace {
    //可以做所有能在全局作用域中做的事
    int val = 9;//全局
    void f() {

    }
    struct MyStruct {
        int age;
        double score;
    };
}

namespace MyNamespace {
    //可以做所有能在全局作用域中做的事
    double foo = 9;//全局
    void g() {

    }
}

  

命名空间可以嵌套:

namespace MyNamespace1 {
    namespace MyNamespace2 {
        namespace MyNamespace3 {
            int age = 100;
        }
    }
}

int main() {
    MyNamespace1::MyNamespace2::MyNamespace3::age = 0;
    return 0;
}

  

命名空间可以取别名:

namespace MyNamespace1 {
    namespace MyNamespace2 {
        namespace MyNamespace3 {
            int money = 100;
        }
    }
}

namespace Space = MyNamespace1::MyNamespace2::MyNamespace3;//取个别名,和命名空间原来的名字等价
using namespace Space;
int main() {
    money = 0;
    return 0;
}

  

using 指示可能会造成冲突:

namespace MyNamespace {
    //可以做所有能在全局作用域中做的事
    double foo = 9;//全局
    void f() {

    }
}

using namespace MyNamespace;
void f() {}


int main() {
    //f();//二义性,编译器可以看见两个f(),不知道调用谁
    MyNamespace::f();//明确指定调用MyNamespace的f()
    ::f();//明确指定调用全局命名空间的f()
    return 0;
}

  

 

二.函数重载

C语言中函数不能同名

C++可以重载函数

构成函数重载的条件:

1.作用域相同

2同名函数

3参数列表不同,参数类型、个数、位置任意一个不同均可

3.1参数类型不同

void f(int) {}

void f(double) {}

3.2参数个数不同

void f(int) {}

void f(int, int) {}

3.3参数位置不同

void f(int, double) {}

void f(double, int) {}

4.返回值和调用约定没有效果

C函数编译后基本只保存了函数名,无法重载。

C++处理函数时,会将作用域,函数名,参数列表,返回值,调用约定等都保存起来。

打开开发人员命令行工具,探索vs的名称粉碎,输入undname可解析函数签名,例如:

 

 头文件中如下写,可以实现C调用C++,或者C++调用C,因为都按C的规则编译:

#pragma once
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus

int myadd(int a, int b);

//其他函数声明
#ifdef __cplusplus
}
#endif // __cplusplus

  

函数重载的二义性:

void f(int) {}
void f(float) {}

void g(int, int arg = 1) {}
void g(int) {}

int main() {
    //f(0.1);//error C2668: “f”: 对重载函数的调用不明确
    //g(1);//error C2668: “g”: 对重载函数的调用不明确
    return 0;
}

  

三.内联inline

有些函数比较简单,调用函数体消耗的时间小于调用准备的时间

内联函数:函数会像宏一样在调用点展开,同时保留函数的类型检查

inline建议编译器展开,是否接受要看编译器。

inline函数具有文件作用域,实现一般放在头文件中。

debug版一般不会内联,即使写了inline关键字

编译选项“内联函数扩展”/Ob0总是不展开,/Ob1写了inline才展开,/Ob2总是尝试展开

 

posted @ 2020-05-08 08:28  八转达人  阅读(196)  评论(0编辑  收藏  举报