• 经典讨论(四)


    一.class和typename

       用class也能够定义函数模板和类模板 


    template<class T>
    T Minus(T a,T b)
    {
    	return a-b;
    }
    
    template<class T>
    class Add
    {
    public:
    	T add(T a,T b)
    	{
    		return a+b;
    	}
    };
    
    
    int main()
    {
    	cout<<Minus(3,4)<<endl;
    	cout<<Minus<float>(0.3,0.4)<<endl;
    	
    	Add<double> ap;
    	cout<<ap.add(10,7)<<endl;
    	cout<<ap.add(0.001,0.1)<<endl;
    	return 0;
    
    }
    

      可是这种代码就编译只是:

    #include <cstdlib>
    #include <iostream>
    using namespace std;
    
    template<typename T, int N>
    class Test
    {
    public:
        typedef T ElemType;
    };
    
    template<class T>
    void func(const T& t)
    {
    	 T::ElemType *p;
    }
    
    
    int main(int argc, char *argv[])
    {
    	
        Test<int, 5> t1;
        func(t1);
     
    	return 0;
    }
    

       解析: 由于编译器并不知道T::ElemType到底是一个类型的名字还是一个变量的名字,编译器自己主动默认ElemType为一个变量名。而不是类型。

    解决的方法仅仅有一个。就是typename T::ElemType *p;

        


    template<class T>
    void func(const T& t)
    {
    	 typename T::ElemType *p;
    }
    
    


     说明: 模板最初的目标仅仅是为了对类类型进行泛型操作的定义,因此用class声明泛型类型。之后的进化过程中。发现了模板相互调用时产生的 :: 操作符符的二义性。因此引入了typename keyword用来告诉编译器将::符号后的标识符看做类型。

    结论: 尽量使用typename取代,可是看一些经典的C++源代码,看见class定义的模板,也可认识即可。


    二. 一个面试题------怎样推断一个变量是否为指针变量

       1. 先回想一个知识点

           C++编译器的匹配调用优先级

             *: 重载函数

             *: 函数模板

             *: 可变參数函数

    #include <cstdlib>
    #include <iostream>
    using namespace std;
    
    void test(int i,int j)
    {
    	cout<<"void test(int i,int j)"<<endl;
    }
    
    template<typename T>
    void test(T i,T j)
    {
    	cout<<"void test(T i,T j)"<<endl;
    }
    
    void test(...)
    {
    	cout<<"void test(...)"<<endl;
    }
    
    int main(int argc, char *argv[])
    {
    	int a=2;
    	int b=3;
    	test(a,b);
    	return 0;
    }
    


       能够一个一个test函数凝视掉,看调用哪个函数,就能够验证C++编译器匹配调用的优先级

    终于得出结论: 函数重载 > 函数模板 > 可变參数函数


    方案1:

    template<typename T>
    bool isPtr(T*)
    {
    	return true;
    }
    
    bool isPtr(...)
    {
    	return false;
    }
    
    int main(int argc, char *argv[])
    {
    	int* pi=NULL;
    	float* pf=NULL;
    	int a=2;
    	int b=3;
    	cout<<isPtr(pi)<<endl;
    	cout<<isPtr(pf)<<endl;
    	cout<<isPtr(a)<<endl;
    	cout<<isPtr(b)<<endl;
    	return 0;
    }
    


    方案二


    template<typename T>
    char isPtr(T*);
    int isPtr(...);
    
    #define ISPTR(v) (sizeof(isPtr(v))==sizeof(char))
    
    int main(int argc, char *argv[])
    {
    	int* pi=NULL;
    	float* pf=NULL;
    	int a=2;
    	int b=3;
    	cout<<ISPTR(pi)<<endl;
    	cout<<ISPTR(pf)<<endl;
    	cout<<ISPTR(a)<<endl;
    	cout<<ISPTR(b)<<endl;
    	return 0;
    }
    

    这个是一个比較经典的面试题,推断一个变量是否为指针变量的。考察的知识点比較多:函数重载,函数模板,可变參数函数,keywordsizeof,宏定义。程序的执行效率问题等等,值得学习的一道面试题。





    版权声明:本文博主原创文章,博客,未经同意不得转载。

  • 相关阅读:
    APP案例分析
    第一次作业
    第0次作业
    结对编程-四则运算
    韩剧TV APP案例分析
    四则运算生成器(基于控制台)
    大学
    JAVA异常机制学习
    散列学习
    PAT 甲级1025 PAT Ranking的
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/4831597.html
Copyright © 2020-2023  润新知