C++ 模板类的默认模板参数、模板函数不支持默认模板参数

 

C++函数模板   C 语言中文网

在这个学期开始学习使用模板,当然模板早在大一期间就用到了一些,但是都是作为练习语法用的。这个学期中使用了大量的模板来进行类的设计与实现,具体的来说应该几乎是这个学期的所有的C++代码都是用的模板实现的吧。有些即使没那么大的使用模板价值,但是还是为了积累模板的经验而硬使用了模板。写了这么多的模板后,也就是在上个星期才偶尔在一个帖子里看到默认模板参数这个概念,写了那么多的代码了才知道这个概念感觉很羞愧啊,就去学习了学习。其实这个如果对照普通类型的默认变量来看待,其实也是不难理解的。

就像标题说的那样:模板类支持默认模板参数、模板函数不支持默认模板参数,这里的模板函数包括全局函数与类成员函数两种。

使用说明一:

[cpp]  view plain copy
  1. //模板类的默认模板参数  
  2. template<class TypeA = intclass TypeB = float>  
  3. class MyClass  
  4. {  
  5. public:  
  6.     TypeA value_A;  
  7.     TypeB value_B;  
  8. public:  
  9.     MyClass(TypeA valA,TypeB valB)  
  10.     {  
  11.         value_A = valA;  
  12.         value_B = valB;  
  13.     }  
  14.     MyClass(){}  
  15.     ~MyClass(){}  
  16.     TypeA GetValueA()  
  17.     {  
  18.         return value_A;  
  19.     }  
  20.     TypeB GetValueB();  
  21.   
  22.     //类成员函数模板  
  23.     template<typename T>  
  24.     void MemberFuntion(T Tval)  
  25.     {  
  26.         cout<<"成员函数模板的类型名: "<<typeid(T).name()<<endl;  
  27.         cout<<"模板成员函数的值: "<<Tval<<endl;  
  28.     }  
  29. };  
  30.   
  31. //默认模板参数的类模板成员函数类外定义方式,在定义这里就不用再声明默认模板参数类型了  
  32. template<class TypeA,class TypeB>  
  33. TypeB MyClass<TypeA,TypeB>::GetValueB()  
  34. {  
  35.     return value_B;  
  36. }  

主函数的调用:

[cpp]  view plain copy
  1. MyClass<> cls(1,2.0f); //因为已经是默认的模板参数了,所以可以不用在实例化类的时候声明类型,但是尖括号是必须要有的  
  2. cout<<cls.GetValueA()<<endl;  
  3. cls.MemberFuntion<float>(11.0f); //成员函数的模板声明方式  

运行的结果是:


使用说明二:
对于主函数还可以这么调用:

[cpp]  view plain copy
  1. MyClass<char,char> clsch('z','l');  //这里主动声明了类模板的参数类型,覆盖了原有的默认模板参数类型  
  2. cout<<"value_A的值: "<<clsch.GetValueA()<<endl;  
  3. cout<<"value_B的值: "<<clsch.GetValueB()<<endl;  
  4. clsch.MemberFuntion<>("hello");  //可以不声明成员函数的模板类型,因为可以根据传进去的参数类型进行匹配模板参数类型。但如果函数没有参数的话,又没有显示的声明类型,那么在静态编译阶段就不能确定模板参数类型,会抛错。  


运行结果:


说明:"hello"的默认类型是常量指针(指向常量字符串的指针),因为一个字符串是被当做是一个常量对待的,存储于常量区。


使用说明三:

[cpp]  view plain copy
  1. //类成员函数模板  
  2. template<typename T = int>  
  3. void MemberFuntion(T Tval)  
  4. {  
  5.     cout<<"成员函数模板的类型名: "<<typeid(T).name()<<endl;  
  6.     cout<<"模板成员函数的值: "<<Tval<<endl;  
  7. }  

如果在成员函数模板中默认模板参数,那么会抛错:error C4519: 仅允许在类模板上使用默认模板参数。


#include <iostream>

using namespace std;


//一样的模式吖,模板实例化的时候不是需要填参数么,这样做目的就是缺省一个啊

template <class TypeA = int , class  TypeB = float>

class MyClass

{

public:

    

    MyClass(TypeA a, TypeB b)

    {

      if(typeid(TypeA) == typeid(TypeB))

      {

          cout << typeid(TypeA).name();

      }

        value_A  = a;

        value_B = b;

    }

    

    virtual ~MyClass(){}

    

    template < class T  > 

    void memberFunc(T val)

    {

  

        cout << typeid(T).name() << endl;  

        // C++ 关键字 typeid, typename

        cout << "模板成员函数的值 :" << val << endl;

    }

    

    template <class T>

    void show( T a);

private:

    TypeA value_A;

    TypeB value_B;

};


template <class TypeA  , class  TypeB> //实现 不要   同事也不能生

template<class T>

inline void MyClass<TypeA, TypeB>::show( T a)

{

    cout << a << '\n';

}


// ***********************************

template <class TypeC>

class MyClass_2 : public MyClass<> //MyClass<TypeA, TypeB>

{

public:

    

    virtual ~MyClass_2<TypeC>() {}  // zhe不是性偶函数

   // MyClass_2(TypeC c, TypeA a, TypeB b);

    MyClass_2(TypeC c);

    

    template <class Type>

    void show(Type a);

    

private:

    TypeC name;

};


template<class TypeC>

//MyClass_2<T>::MyClass_2(int a, int b, int c):MyClass(b, c)  不对啊

//{

//    name = a;

//}

MyClass_2<class TypeC>::MyClass_2(TypeC c)

{

    name = c;

}


//  lei 模版中的 模版函数

template <class T>

template <class Type>

void MyClass_2<T>::show(Type a)

{

    

}


int main(int argc, const char * argv[])

{

// 模板类的默认模板参数、模板函数不支持默认模板参数

    MyClass<> obj(1, 2.0);                  //

    obj.memberFunc<float>(11);              //

    

    

    obj.show<int>(10);

    

    return 0;

}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
I.引言 在Basic(俺的入门语言),Pascal等语言中都提供了定长字符串类型,各有特色,Basic的 是长度固定,超出截断,不足补空格;;pascal的是最大长度限制在某个范围. 虽然定长字符串有这样那样的缺点(例如长度有限,弄不好会丢失数据;;) 定长字符串还是有一定的好处,主要是: 1.不分配在堆上,从而不会造成内存碎片 2.静态分配内存,分配速度快 因此我写了一个定长字符串类,用作轻量级的字符串.类似于pascal的定长字符串,也采用也采取饱和的方式来处理溢出. II.简介 主要类有: 1. template<;typename T,typename Traits=std::char_traits<;T>; >; class basic_small_string_base;; 这是定长字符串的基类,适用于各种字符类型,当然也支持";火星人的三字节字符";. 模板类的代码主要实现在该类中.该类是抽象类,不能够实例化. 2. template<;typename T, size_t MaxSize, typename Traits=std::char_traits<;T>; >; class basic_small_string;; // : public basic_small_string_base<;T,Traits>; 特定长度的定长字符串模板类.如果C++标准支持模板typedef的话,下面的4的俩类就不用再写了,遗憾的是还不支持,所以他也是抽象类.//其实做成可实例化的类也没任何问题。 3. typedef basic_small_string_base<;char, std::char_traits<;char>; >; small_string_base;; typedef basic_small_string_base<;wchar_t, std::char_traits<;wchar_t>; >; small_wstring_base;; 针对char和wchar_t(我特讨厌这后面的_t这根尾巴)两种字符类型的基类的和默认traits 的typedef.写函数参数类型的时候可以少写几个字, ^=^ 4. template <;size_t MaxSize, typename Traits=std::char_traits<;char>; >; class small_string;; // : public basic_small_string<;char, MaxSize,Traits>; 这是定长字符串的基类,适用于各种字符类型,当然也支持";火星人的三字节字符";. 模板类的代码主要实现在该类中.该类是抽象类,不能够实例化. 2. template<;typename T, size_t MaxSize, typename Traits=std::char_traits<;T>; >; class basic_small_string;; // : public basic_small_string_base<;T,Traits>; 特定长度的定长字符串模板类.如果C++标准支持模板typedef的话,下面的4的俩类就不用 再写了,遗憾的是还不支持,所以他也是抽象类.//其实做成可实例化的类也没任何问题。 3. typedef basic_small_string_base<;char, std::char_traits<;char>; >; small_string_base;; typedef basic_small_string_base<;wchar_t, std::char_traits<;wchar_t>; >; small_wstring_base;; 针对char和wchar_t(我特讨厌这后面的_t这根尾巴)两种字符类型的基类的和默认traits 的typedef.写函数参数类型的时候可以少写几个字, ^=^ 4. template <;size_t MaxSize, typename Traits=std::char_traits<;char>; >; class small_string;; // : public basic_small_string<;char, MaxSize,Traits>; template <;size_t MaxSize, typename Traits=std::char_traits<;wchar_t>; >; class small_wstring;; // : public basic_small_string<;char, MaxSize, Traits>; 真正能实例化的ANSI和WCHAR版本的定长字符串类. III.用法 该模板类用法和std::string一样,可以参考它的文档.另外为了兼容std::basic_string<;>;, 还提供了和std::string搭配的一些额外功能,比如函数的字符串参数支持 std::basic_string.可以与std::basic_string<;>;进行比较,转换,连接等. 1. 包含头文件 #include";small_string.hpp"; 2.引入cfc命名空间 using namespace;; // 可以略去 3.实例化对象 cfc::small_string<;16>; s=";hello";;; // 一个缓冲区长度为16的定长字符串,内容为";hello"; // 最大长度为15,而不是16,注意! 作局部变量时效率上基本上等于 char s[]=";hello";;;低于char *s=";hello";;;原因很简单. 可以和std::string协同操作: std::string s3 = s;; s = s3;; 4.作为函数参数 作为非模板函数参数传递时,参数的类型应该写成cfc::small_string_base&或者 cfc::small_wstring_base& ,根据需要,可以加上const: void foo(cfc::small_string_base& str) { str=";hello";;; } int main() { cfc::small_string<;32>; s;; foo(s);; } 其他插入,比较,删除等操作跟std::string一样 IV.实现 利用模板的最大缓冲区长度参数,实例化模板,把缓冲区作为数组直接建立在对象的内部. 为了减少代码膨胀,大部分功能都移入基类. V.结尾. 由于时间仓促,经历有限,经验不足,缺点错误肯定不少,欢迎大家批评指正. 谢谢!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值