Chinaunix首页 | 论坛 | 博客
  • 博客访问: 774616
  • 博文数量: 239
  • 博客积分: 60
  • 博客等级: 民兵
  • 技术积分: 1045
  • 用 户 组: 普通用户
  • 注册时间: 2009-03-22 18:25
文章分类

全部博文(239)

文章存档

2019年(9)

2018年(64)

2017年(2)

2016年(26)

2015年(30)

2014年(41)

2013年(65)

2012年(2)

分类: C/C++

2014-02-11 18:07:45

    C++运行时多态用于让从基类继承的多个对象呈现不同行为。而今,我们使用子类成员模板和基类的虚方法,让同一对象的基类指针与子类指针在调用虚方法时,呈现编译时多态行为。
[Example:

点击(此处)折叠或打开

  1. // member_function_template.cpp
  2. #include <iostream>

  3. using namespace std;

  4. class B
  5. {
  6. public:
  7.     virtual void f(int)
  8.     {
  9.         cout<<"[virtual void B::f(int)] called\n"<<endl;
  10.     }

  11.     virtual void fSec(int)
  12.     {
  13.         cout<<"[virtual void B::fSec(int)] called\n"<<endl;
  14.     }
  15. };

  16. class D : public B
  17. {
  18. public:
  19.     template <class T> void f(T) // does not override B::f(int)
  20.     {
  21.         cout<<"[template void D::f(T)] called\n"<<endl;
  22.     }

  23.     void f(int i) // overriding function that calls, the template instantiation
  24.     {
  25.         cout<<"[void D::f(int i)] called"<<endl;
  26.         f<>(i);
  27.     }

  28.     template <class T> void fSec(T) // does not override B::f(int)
  29.     {
  30.         cout<<"[template void D::fSec(T)] called\n"<<endl;
  31.     }
  32. };

  33. int main(int argc, char* argv[])
  34. {
  35.     int para = 1;
  36.     D sub;

  37.     B* base = &sub;
  38.     D* subTemp = &sub;
  39.     

  40.     cout<<"[ base->f(para); ] is running"<<endl;
  41.     base->f(para);

  42.     cout<<"[ subTemp->f(para); ] is running"<<endl;
  43.     subTemp->f(para);

  44.     cout<<"[ sub.f(para); ] is running"<<endl;
  45.     sub.f(para);

  46.     /////////////////
  47.     cout<<"[ base->fSec(para); ] is running"<<endl;
  48.     base->fSec(para);

  49.     cout<<"[ sub->fSec(para); ] is running"<<endl;
  50.     subTemp->fSec(para);

  51.     cout<<"[ sub.fSec(para); ] is running"<<endl;
  52.     sub.fSec(para);

  53.     return 0;
  54. }
Result:

点击(此处)折叠或打开

  1. [ base->f(para); ] is running
  2. [void D::f(int i)] called
  3. [template <class T> void D::f(T)] called

  4. [ subTemp->f(para); ] is running
  5. [void D::f(int i)] called
  6. [template <class T> void D::f(T)] called

  7. [ sub.f(para); ] is running
  8. [void D::f(int i)] called
  9. [template <class T> void D::f(T)] called

  10. [ base->fSec(para); ] is running
  11. [virtual void B::fSec(int)] called

  12. [ sub->fSec(para); ] is running
  13. [template <class T> void D::fSec(T)] called

  14. [ sub.fSec(para); ] is running
  15. [template <class T> void D::fSec(T)] called

示例结果分析:
    语句subTemp->fSec(para);和base->fSec(para);输出了不同的结果,但是它们指向的是同一个对象。产生这个结果是由于子类方法的模板在编译时被生成,而类成员函数模板不能是virtual 虚方法,没有被加入类虚表,只是在编译时作了函数方法匹配,成就了另类的多态。
    如果希望子类的虚方法继续有效,需要使用非模板成员函数覆盖基类虚方法,用于将其添加到类虚表中。如语句base->f(para);和subTemp->f(para);输出相同结果。
— end example]

    附上:

点击(此处)折叠或打开

  1. 14.5.2 Member templates [temp.mem] ISO/IEC 14882:2011(E)

  2. A template can be declared within a class or class template; such a template is called a member template. A member template can be defined within or outside its class definition or class template de?nition. A member template of a class template that is de?ned outside of its class template definition shall be speci?ed with the template-parameters of the class template followed by the template-parameters of the member template.
  3. [ Example:

  4. template<class T> struct string {
  5. template<class T2> int compare(const T2&);
  6. template<class T2> string(const string<T2>& s) { /? ... ?/ }
  7. };

  8. template<class T> template<class T2> int string<T>::compare(const T2& s) {
  9. }

  10. end example ]

  11. A local class shall not have member templates. Access control rules (Clause 11) apply to member template names. A destructor shall not be a member template. A normal (non-template) member function with a given name and type and a member function template of the same name, which could be used to generate a specialization of the same type, can both be declared in a class. When both exist, a use of that name and type refers to the non-template member unless an explicit template argument list is supplied. [ Example:

  12. template <class T> struct A {
  13. void f(int);
  14. template <class T2> void f(T2);
  15. };

  16. template <> void A<int>::f(int) { } // non-template member
  17. template <> template <> void A<int>::f<>(int) { } // template member

  18. int main() {
  19. A<char> ac;
  20. ac.f(1); // non-template
  21. ac.f(’c’); // template
  22. ac.f<>(1); // template
  23. }

  24. end example ]
  25. 3  A member function template shall not be virtual. [ Example:
  26.  
  27. template <class T> struct AA {
  28. template <class C> virtual void g(C); // error
  29. virtual void f(); // OK
  30. };

  31. end example ]

  32. A specialization of a member function template does not override a virtual function from a base class.
  33. [ Example:

  34. class B {
  35. virtual void f(int);
  36. };

  37. class D : public B {
  38. template <class T> void f(T); // does not override B::f(int)
  39. void f(int i) { f<>(i); } // overriding function that calls
  40. // the template instantiation
  41. };

  42. end example ]

  43. A specialization of a conversion function template is referenced in the same way as a non-template conversion function that converts to the same type. [ Example:

  44. struct A {
  45. template <class T> operator T*();
  46. };
  47. template <class T> A::operator T*(){ return 0; }
  48. template <> A::operator char*(){ return 0; } // specialization
  49. template A::operator void*(); // explicit instantiation

  50. int main() {
  51. A a;
  52. int *ip;
  53. ip = a.operator int*(); // explicit call to template operator
  54. // A::operator int*()
  55. }

  56. end example ] [ Note: Because the explicit template argument list follows the function template name, and because conversion member function templates and constructor member function templates are called without using a function name, there is no way to provide an explicit template argument list for these function templates.end note ]

  57. A specialization of a conversion function template is not found by name lookup. Instead, any conversion function templates visible in the context of the use are considered. For each such operator, if argument deduction succeeds (14.8.2.3), the resulting specialization is used as if found by name lookup.

  58. A using-declaration in a derived class cannot refer to a specialization of a conversion function template in a base class.
  59. Overload resolution (13.3.3.2) and partial ordering (14.5.6.2) are used to select the best conversion function among multiple specializations of conversion function templates and/or non-template conversion functions.

阅读(1210) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~