作者yoco315 (眠月)
看板C_and_CPP
标题Re: [语法] Template与Inheritance结合??
时间Tue Apr 18 10:29:16 2006
※ 引述《clifftsai (噜来噜肥)》之铭言:
: template
: <
: class ThreadLock
: >
: class FSDB : ThreadLock
先看两种大家都很熟悉的语法
┌───────────────────────────
│
template < class T >
│
class Foo
│
{
│
T value ;
│
} ;
└───────────────────────────
很单纯的 class template,看你 T 给什麽型别,value 就是什麽型别。
┌───────────────────────────
│
class Foo : Bar
│
{
│
...
│
} ;
└───────────────────────────
很简单的继承,Foo 继承 Bar,没有指明继承的形式表示是 private 继承。
然後两者合一
┌───────────────────────────
│
template < class T >
│
class Foo : T
│
{
│
...
│
} ;
└───────────────────────────
看起来很玄,其实就是
Foo 继承 T,
不过这个 T 是个 template,
看你
T 给什麽型别,Foo 就继承什麽型别,
没有指明继承的形式表示是 private 继承。
当你写 Foo<A> 表示是一个 "Foo 继承 A" 的型别
当你写 Foo<B> 表示是一个 "Foo 继承 B" 的型别
当你写 Foo<C> 表示是一个 "Foo 继承 C" 的型别
就是这样。
Loki::Typelist 还有用到类似这样的写法
┌───────────────────────────
│template < class
T, template <class> class
U >
│Foo :
T <
U >
│{
│}
└───────────────────────────
这个 Foo 有两个型别参数,
而且第一个型别必须是一个 class template,
Foo 继承了 "
T 以 U 具现" 这个型别,
看起来很酷,不过除了很酷以外,这可以干嘛?
这可以用来实作
HierarchyGenerators 技术。
有的时候你需要一系列的 data member 跟是 member funciton
但是 template 在这个地方似乎就像个婴儿一样无能为力
这个时候你唯一的选择好像就是复制贴上
举个例子来说
我要设计一套影像处理类别库
在设计一些基础的影像类别的时候
我想要遵行「实作与介面分离的抽象性」
所以我不准备提供任何 public 的 data member
取而代之的是我准备为每个 data member 提供一个 function 来存取 data member
像这样
┌───────────────────────────
│class RGB_Image
│{
│ private :
│ Array2D R_ ;
│ Array2D G_ ;
│ Array2D B_ ;
│ public :
│ Array2D & R() { return R_ ; }
│ Array2D & G() { return G_ ; }
│ Array2D & B() { return B_ ; }
│} ;
└───────────────────────────
然後当我准备设计另外一种影像类别的时候,例如 Lab
那就是这样
┌───────────────────────────
│class Lab_Image
│{
│ private :
│ Array2D L_ ;
│ Array2D a_ ;
│ Array2D b_ ;
│ public :
│ Array2D & L() { return L_ ; }
│ Array2D & a() { return a_ ; }
│ Array2D & b() { return b_ ; }
│} ;
└───────────────────────────
然後我还要提供一种 YMCK 的影像类别
┌───────────────────────────
│class YMCK_Image
│{
│ private :
│ Array2D Y_ ;
│ Array2D M_ ;
│ Array2D C_ ;
│ Array2D K_ ;
│ public :
│ Array2D & Y() { return Y_ ; }
│ Array2D & M() { return M_ ; }
│ Array2D & C() { return C_ ; }
│ Array2D & K() { return K_ ; }
│} ;
└───────────────────────────
大家都是聪明人,已经发现到我在作重工,
这些千篇一律的白痴程式码正在不断腐蚀着程式设计师的脑细胞,
然後如果我还打算提供 HSV 或是其他等等等等的影像格式的话,
那我就要继续这些重复性很高的智障程式码。
其实复制贴上也不过就是按个两下,没什麽难,
问题是在於,手工的东西多了,错误的机会就会增加,
而且以後修改跟扩充的难度会比较高。
这些程式码明明就有很高的重复性,
但是你好像没办法用 template 来解决这个问题。
事实上是可以的,
Loki::HierarchyGenerator 成功的利用 template 把这样的程式码生成机制自动化。
(HierarchyGenerator 有两种)
我现在可以这样做
┌───────────────────────────
│template < typenamep T >
│class Holder
│{
│
private: T value_ ;
│
public: T & value() { return value_ ; }
│} ;
│
│typedef TYPELIST_3 ( Array2D, Array2D, Array2D ) RGB_Typelist ;
│typedef TYPELIST_3 ( Array2D, Array2D, Array2D ) HSV_Typelist ;
│typedef TYPELIST_3 ( Array2D, Array2D, Array2D ) Lab_Typelist ;
│typedef TYPELIST_4 ( Array2D, Array2D, Array2D, Array2D ) YMCK_Typelist ;
│
│typedef Loki::GenScatterHierarchy < RGB_Typelist , Holder > RGB_Image ;
│typedef Loki::GenScatterHierarchy < HSV_Typelist , Holder > HSV_Image ;
│typedef Loki::GenScatterHierarchy < Lab_Typelist , Holder > Lab_Image ;
│typedef Loki::GenScatterHierarchy < YMCK_Typelist, Holder > YMCK_Image ;
└───────────────────────────
尽管很难相信,但我已经定义完这四种影像型别了,
每一个 class 都有该有的 data member 以及相对应用来存取的 member function,
而且之後每新增一种类别只需要多两行程式码来 typedef,
如果你觉得每次宣告物件的时候可以很勤劳的打上全名没关系,
那连这两行都可以省去。
你可以这样存取每一个资料成员..
RGB_Image img ;
Loki::Field<0>(img).value() = ...
Loki::Field<1>(img).value() = ...
Loki::Field<2>(img).value() = ...
真是酷!
Loki::HierarchyGenerators 会根据你给的 Typelist,
(就是一串型别,像是这样 int, int, double, Foo, Bar )
使用递回继承自己的方法,
来让最後一个类别拥有全部所需的 data member 跟 member function。
我这边只是讲一下他可以怎麽用,
实作细节有兴趣的话可以看 《Modern C++ Design》。
-
感谢大家的指正跟补充 @@
HierarchyGenerator 只是 Typelist 一个主要的应用,
我把两者混在一起是错误的。
另外我弄错预设的继承属性真是天大的笑话 XD 抱歉万分
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 140.113.129.180
※ 编辑: yoco315 来自: 140.113.129.180 (04/18 10:30)
1F:推 qrtt1:好详细啊XD 04/18 10:41
2F:推 cplusplus:恩 好多字啊 XD 辛苦呀 04/18 10:48
3F:推 UNARYvvv:酷~ 04/18 11:21
4F:推 SHBK:没有指名继承形式的话default 是 private derivation? 04/18 12:07
5F:推 sunkill:对 书上看到的也是 private 不过还是推 04/18 13:12
6F:→ yoco315:我常常犯错 QQ 大家发现的时候记得嘲笑我 QQ 04/18 13:15
7F:推 godfat:参考 Loki::Tuple 04/18 13:57
※ 编辑: yoco315 来自: 140.113.129.180 (04/18 18:28)
8F:推 yaca:真的很详细,感谢大大的用心 04/18 23:24
9F:推 SHBK:瑕不掩瑜 好文推一个 下面那篇也是好文 04/19 00:20