下述内容,均从C++ primer进行摘录总结:
一)重载的定义:
如果同一个作用域内的几个函数名字相同但形参列表不同。提示:main函数不能进行重载
void print(const int ia[], size_t size); //两个重载函数
void print(const int *beg, const int *end);
二)重载和const形参
我们通过 底层const进行函数重载
//合法的,区别是他们的引用类型的形参是否引用了常量,属于底层const
int calc(char, char);
int calc(const char&, char const&);
//合法的,区别是他们的指针类型的形参是否指向了常量,属于底层const
int calc(char*, char*);
int calc(char const*, char const*);
//非法的重载:两个函数的区别是他们形参本身(指针类型)是否为常量
//属于顶层const,属于精确匹配范畴:向实参添加顶层const或者从实参中删除顶层const
int calc(char a, char b);
int calc(char* const, char* const);
注意:我们可以通过
const_cast进行const重载,有效避免重复代码的产生
int calc(char* s1, char* s2)
{
return calc(const_cast<char const*>(s1), const_case<char const*>(s2));
}
三)重载与引用
①我们可以通过改变参数的左值引用和右值引用进行重载,如下所示
class StrVec{
public:
void push_back(const std::string&); //拷贝元素
void push_back(std::string&&); //移动元素
};
②我们可以通过引用限定符来区分重载函数
class Foo{
friend Foo &retFoo(); //返回一个引用
friend Foo retVal(); //返回一个右值
public:
Foo sorted() &&; //可用于可改变的右值
Foo sorted() const &; //可用于任何类型的Foo,注意&不能省
//此外引用限定符的另一个作用:只能向可修改的左值赋值
Foo& operator=(const Foo&) &;
//Foo j;
//retFoo() = j; //正确
//retVal() = j; //错误,retVal返回一个右值
private:
vector<int> data;
};
//本对象为右值(对象状态可改变),因此可以进行原址排序
Foo Foo::sorted()&&{
sort(data.begin(), data.end());
return *this;
}
//被对象是const或一个左值,那种情况我们都不能对原址排序
Foo Foo::sorted() const &{
Foo ret(*this);
sort(ret.data.begin(), ret.data.end());
return ret;
}
//通过调用对象时左值还是右值决定调用哪一个
retFoo.sorted(); //左值,调用Foo Foo::sorted() const &
retVal.sorted(); //右值,调用Foo Foo::sorted()&&
四)重载与模板
①通过显示模板参数消除函数调用指针的歧义;
//定义一个函数模板
template <typename T> int compare(const T &v1, const T &v2);
//定义重载函数
void func(int (*)(const string&, const string&);
void func(int (*)(const int& , const int&);
func(compare); //错误,使用compare的那个实力
func(compare<int>); //正确,显示指示实例化那个版本
②当有多个重载模板对一个调用提供同样好的匹配时,应选择最特例化的一个;
//由于为const T&,本质上可以接受任意类型(特例化为左值或const右值)
//注意(T&&也可接受任意类型,特例为非const右值)
template <typename T> std::string debug_rep(const T &t);
//该模板主要针对指针类型
template <typename T> std::string debug_rep(T *p);
//考虑下面的调用那个
string s("hello");
const string *sp = &s;
cout<< debug_rep(sp) << endl; //选择template <typename T> std::string debug_rep(T *p),该目标更特例
③对于一个调用,如果一个非函数模板与一个函数模块提供同样好的匹配时,选择非模板版本;
//模板
template <typename T> std::string debug_rep(const T &t);
//普通函数
std::string debug_rep(const std::string &s);
//考虑下面调用
string s("hi");
cout<< debug_rep(s)<<endl; //选择普通函数进行调用
④模板特例化的本质是实例化一个模板,而非重载它。因此,特例化不影响匹配;
#include <iostream>
using std::cout; using std::endl;
#include <functional>
using std::less;
#include <cstring>
using std::strcmp;
// version of compare that will be correct even if used on pointers
template <typename T> int compare(const T &v1, const T &v2)
{
cout << "compare(T)" << "\t";
if (less<T>()(v1, v2)) return -1;
if (less<T>()(v2, v1)) return 1;
return 0;
}
template<unsigned N, unsigned M>
int compare(const char (&p1)[N], const char (&p2)[M])
{
cout << "compare(const char arrays)" << "\t";
return strcmp(p1, p2);
}
template<>
int compare(const char *const& p1, const char *const& p2)
{
cout << "compare(const char*const)" << "\t";
return strcmp(p1, p2);
}
int main()
{
int *p1 = new int(45);
int *p2 = new int(42);
// because we're comparing pointer values, the result of
// this call may vary each time the program is run
cout << compare(*p1, *p2) << endl; //调用template <typename T> int compare(const T &v1, const T &v2)
cout << compare(p1, p2) << endl; //调用template <typename T> int compare(const T &v1, const T &v2)
cout << strcmp("hi", "mom") << endl;
cout << compare("hi", "mom") << endl; //字面值常量字符串,调用template<unsigned N, unsigned M>
//int compare(const char (&p1)[N], const char (&p2)[M])
const char *cp1 = "hi", *cp2= "mom"; //
cout << compare(cp1, cp2) << endl; //调用其特例化版本,
//template<> int compare(const char *const& p1, const char *const& p2)
return 0;
}
//打印结果
compare(T) 1
compare(T) -1
-1
compare(const char arrays) -1
compare(const char*const) -1
--------------------------------
Process exited after 0.02734 seconds with return value 0
请按任意键继续. . .