我正在使用一個簡單的對象模型,其中對象可以實現接口來提供可選功能。在它的心臟,一個對象必須實現getInterface
方法,該方法被賦予一個(唯一的)接口ID。然後該方法返回一個指向接口的指針 - 或null,以防對象沒有實現所請求的接口。這裏有一個代碼草圖來說明這一點:這個基於類型列表的類層次結構生成代碼的替代方案是什麼?
struct Interface { };
struct FooInterface : public Interface { enum { Id = 1 }; virtual void doFoo() = 0; };
struct BarInterface : public Interface { enum { Id = 2 }; virtual void doBar() = 0; };
struct YoyoInterface : public Interface { enum { Id = 3 }; virtual void doYoyo() = 0; };
struct Object {
virtual Interface *getInterface(int id) { return 0; }
};
爲了讓事情變得更容易了誰在這個框架內合作的客戶,我用一個小模板,自動生成「getInterface」實施,使客戶只需要執行接口所需的實際功能。這個想法是從Object
以及所有的接口派生出一個具體類型,然後讓getInterface
只返回指向this
(轉換爲正確類型)的指針。這裏的模板和演示用法:
struct NullType { };
template <class T, class U>
struct TypeList {
typedef T Head;
typedef U Tail;
};
template <class Base, class IfaceList>
class ObjectWithIface :
public ObjectWithIface<Base, typename IfaceList::Tail>,
public IfaceList::Head
{
public:
virtual Interface *getInterface(int id) {
if (id == IfaceList::Head::Id) {
return static_cast<IfaceList::Head *>(this);
}
return ObjectWithIface<Base, IfaceList::Tail>::getInterface(id);
}
};
template <class Base>
class ObjectWithIface<Base, NullType> : public Base
{
public:
virtual Interface *getInterface(int id) {
return Base::getInterface(id);
}
};
class MyObjectWithFooAndBar : public ObjectWithIface< Object, TypeList<FooInterface, TypeList<BarInterface, NullType> > >
{
public:
// We get the getInterface() implementation for free from ObjectWithIface
virtual void doFoo() { }
virtual void doBar() { }
};
這工作得很好,但有兩個問題,這是醜陋的:
一種我阻滯劑是,這並不MSVC6工作(對模板的支持很差,但不幸的是我需要支持它)。編譯時,MSVC6會產生C1202錯誤。
通過遞歸
ObjectWithIface
模板生成整個範圍的類(線性層次結構)。這對我本身來說不是問題,但不幸的是,我不能只用一條switch
語句將接口ID映射到getInterface
中的指針。相反,層次結構中的每個步驟都會檢查單個接口,然後將請求轉發給基類。
有沒有人有建議如何改善這種情況?要麼通過修復ObjectWithIface
模板的上述兩個問題,要麼通過建議使對象/接口框架更易於使用的替代方法。
如果您需要支持VC6,我認爲您在模板元編程技巧方面的選擇是有限的。 – jalf 2011-01-19 13:05:45
@jalf:我肯定是有限的,是的 - 我仍然希望在這些限制內有所改善。 : - ] – 2011-01-22 08:55:40