C++同名函数选择,命名空间

同名函数的选择

  • 同名函数的情况,可以出现于函数重载或者有模板函数的情况下,弄清各个函数的调用优先级以及报错的情况有必要
void may(int);

float may(float, float y=3);

void may(char);

char * may(const cahr & );

template<class T> void may(const T &);

template<class T> void may(T *);

编译器选择匹配的函数顺序如下 :
1. 完全匹配。参数列表和返回类型完全匹配,不需要任何转化。其中,常规函数>显示具体化>普通模板.
2. 提升转换。形参和实参并非完全匹配,带入的实参会自动转化为形参的类型,精度不会改变,是安全的转化。char short 转为 int, float 转为double
3. 标准转化。可能会丢失精度。int 转为 char ,long 转为double。

完全匹配 和最佳匹配
  • 以下的转化都可以视为完全匹配,其中type 泛指任何一种类型。
实参形参
typetype &
type &type
type []*type
type (arguement-list)type * (arguement-list)
typeconst type
typevolatile type
type *const type
type *volatile type*

所以,以下4个都是完全匹配,从报错中明显可见

void test(int);
void test( const int);
void test(int &);
void test(const int &);

image

  • 只有上面的第1 、2个,由于完全匹配将会编译出错,这个并不难理解,编译器发现了两个都可以匹配的不知道匹配哪个。

image

  • 只有第3、4个,编译没有任何问题。并且可以看出,选择的是无const 版本,对于引用类型和指针类型都是这样。而对于实参是const 的类型, 由于非const指针不能指向const,选取const形参函数是理所应当的。
void test(int &)
{
    cout << " I'm void test(int &);" << endl;
}
void test(const int &)
{
    cout << " I'm void test(const int  &);" << endl;
}

void test(int *)
{
    cout << " I'm void test(int *);" << endl;
}
void test(const int *)
{
    cout << " I'm void test(const int *);" << endl;
}
int main()
{
    int a = 5;
    const int b = 10;

    test(a);
    test(b);

    test(&a);
    test(&b);

    cin.get();
    return 0;
}

image

自定义匹配
  • 也就是使用者指定使用哪个,比如虽然有模板和普通函数,由于某些原因,我希望编译器使用模板。
void cal(double x, double y)
{
    cout << "int cal(int x, int y)  :" <<  x+y <<endl;
}

template <typename T>
void cal(T x, T y)
{
    cout << "T cal(T x, T y)   :" <<x+y <<endl;
}

int main()
{
    double  x = 1.6; 
    double y = 2.7;

    cal(x,y);
    cal<>(x, y);
    cal<int >(x, y);
    cin.get();

    return 0;
}

image

从结果看,确实根据使用者需要,调用了相应的函数。

无法确定的模板变量类型处理
template <typename T1, typename T2>
void test(T1 x ,T2 y)
{
    A =x+y;
}

对于上述的代码将会出现一个问题,无法预先知道A的类型。可以使用函数decltype()

decltype(x+y) A =x+y;//根据x+y的类型确定变量类型,由编译器确定

//对于函数返回类型

template <typename T1, typename T2>
auto test(T1 x ,T2 y) ->decltype(x+y);

1、volatile进行优化,强制编译器从硬件中读取。虽然程序没有改变某个内存的值,但是硬件可能根据条件使内存变化,比如串口接受数据

2、mutable 指出,即使结构体或者变量被定义为const类型,内部的某个参数仍然可变。

struct data
{
    mutable int a;
    int b;
}

const data x ={12};
x.a=5;       //这是可行的

3

名空间

定义一个名空间

namespace Jack{
    double x;
    int y;
}
  • 为名空间扩展内容;为名空间内的函数实现定义
namespace Jill{
    char *goose (const char *);
}

namespace Jack{
    void test()
    {
    }
}
  • 名空间作用域解析,
Jack::x=3.5;
Jack::y=8;
using声明 和 using编译指令
  • 为了免去每次使用名空间解析的繁琐,可以使用using 一次性声明某个名空间内的内容。使得解析后的内容的可用范围在使用using声明块内。
int main()
{
    using Jill::test;
}
  • 使用using 编译指令使得对应名空间内内容均可用
using namespace Jill;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值