我有以下内容:
class Foo {};
class Bar : public Foo {};
template <class T>
class TemplatedClass : public T {};
class SpecializedClass : public TemplatedClass<Foo> {};
我需要一个新班级,
class RespecializedClass : public TemplatedClass<Bar> {};
但是这个新类与SpecializedClass
完全相同,只是它专注于Bar
,这是一个派生自Foo
的类。它将简单地复制粘贴SpecializedClass
,但是我必须维护两个相同的代码行。
有没有办法从RespecializedClass
派生 SpecializedClass
,但是还要将模板数据类型专门化为子数据类型?
我给出了以下类的层次结构:
class X {};
class A {};
template <class T>
class B : public T, public A {};
class C : public B<X> {};
class D : public C {};
我无法触及X
,A
,B
,C
和D
背后的任何来源。我只能从中衍生出来并扩展它们。
现在,我从X
派生了一个新类 - 将其称为小写x
。 (我通常不会在一个设置中使用X
和x
,但在这种情况下,视觉相似性在这种情况下很有用。)
class x : public X {};
我需要的是一个与D
相同但在x
而不是X
上模板化的类。
当然,我可以简单地复制粘贴C
和D
并将其专门化为x
,如下所示:
class c : public B<x> {};
class d : public c {};
但是,只要C
和D
被修改,我就必须维护此代码。
有没有办法做类似
的事情class d : public D, public B<x> {};
在层次结构中进一步“重新指定”模板的数据类型?
无需阅读本段;事实上,它可能比启发更容易混淆。我需要d
x
而不是X
模板的原因是x
和{{1}封装数据库表,并编写X
来更新它模板化的任何表。为了更接近事实,我正在使用的基础架构自动生成所有数据库表的封装类。在数据库字典中,可以配置“派生”表,该表继承来自另一个表的所有字段和键,然后使用其他字段和键扩展该表。基础结构不仅自动生成这些“派生”表的封装类,而且实际上将它们表示为各自父类的派生类。所以,实际上我实际上并不是编码 B
- 它正在为我自动生成,作为x
的子类。我需要的是,现在我可以更精确,是一个所有 X
所做的类,但是在数据库表D
上运行,而不是{{ 1}}。
答案 0 :(得分:2)
有没有办法从SpecializedClass派生RespecializedClass,但是进一步将模板数据类型专门化为子数据类型?
不。至少,没有您无法触及SpecializedClass
实施的约束。
如果你可以更改它,你应该改变它:
旧代码:
template <class T>
class TemplatedClass : public T {};
class SpecializedClass : public TemplatedClass<Foo> {};
新代码:
template <class T>
class TemplatedClass : public T {};
template<type Base = Foo> // << HERE
class SpecializedClass : public TemplatedClass<Base> {};
因为你不能这样做,所以你有以下几种可能:
滚动你自己的SpecializedClass:如你所说,将SpecializedClass复制到你自己的专门化中(类似于上面的“新代码”,然后添加:using RespecializedClass = SpecializedClass<Bar>;
)。然后,使用新的SpecializedClass维护所有代码(直接称它为RespecializedClass?:))并忽略原始库提供的代码。您必须将原始代码中的修补程序和修补程序传播到您自己的副本中:(
向公司的原始维护人员提出补丁,解释您的具体需求。如果您为Base
提供默认模板参数,则公司内的客户端代码可以在不需要任何更改的情况下运行。
答案 1 :(得分:1)
如果您的目标是最大限度地减少代码重复,我认为最简单的方法就是将您的可共享代码编写为模板,而不是干涉您的ORM库继承树。您的模板将能够对他们操作的类型做出所需的假设(界面类似于D
)。
现在,关于问题的简化陈述,如果要重新指定的类的方法在TemplatedClass
中声明为虚拟,那么从两者手动SpecializedClass
派生它不应该是一个问题TemplatedClass<Bar>
和SpecializedClass
,并执行正确的内部管道。否则,您将无法使用RespecializedClass
代替SpecializedClass
。剩下的解决方案是为这些创建适配器类,并为适配器编写代码,或者使用本文开头的模板化代码解决方案。
答案 2 :(得分:1)
鉴于您的层次结构:
class X {};
class A {};
template <class T> class B : public T, public A {};
class C : public B<X> {};
class D : public C {};
你可以使B的每个子类也成为一个类模板:
template <class T> class CT: public B<T> {};
template <class T> class DT: public C<T> {};
类模板CT
和DT
由您控制,因此您可以为T==x
专门设置它们。只是为了测试,定义一些与旧类C
和D
相等的模板别名:
using class CX = C<X>; // equal to your old C
using class DX = D<X>; // equal to your old D
然后你还需要两个typedef来获取你需要的类:
using class Cx = C<x>;
using class Dx = D<x>;