[英]C++: partial implementation of a template class
Suppose I have a hierarchy of two classes:假设我有两个类的层次结构:
class Base {
public:
virtual ~Base() {}
virtual int next(int x) const { return x+1; }
};
class Derived: public Base {
public:
virtual int prev(int x) const { return x-1; }
};
I want to create a Modifier
class template that could apply to both Base
and Derived
and changes the behaviour of next()
(if used with Base
) or both next() and prev()
(if used with Derived
).我想创建一个可以同时应用于Base
和Derived
的Modifier
类模板,并更改next()
(如果与Base
一起使用)或 next() 和prev()
(如果与Derived
一起使用)的行为。 Here is an inelegant solution with code duplication:这是一个带有代码重复的不雅解决方案:
template<class BaseOrDerived> class Modifier;
template<> class Modifier<Base>: public Base {
const Base& obj;
const int k;
public:
Modifier(const Base& _obj, int _k) : obj(_obj), k(_k) {}
virtual int next(int x) const { return obj.next(x)+k; }
};
template<> class Modifier<Derived>: public Derived {
const Derived& obj;
const int k;
public:
Modifier(const Derived& _obj, int _k) : obj(_obj), k(_k) {}
virtual int next(int x) const { return obj.next(x)+k; }
virtual int prev(int x) const { return obj.prev(x)-k; }
};
Now the question: how to do this better?现在的问题是:如何更好地做到这一点? Can I write down the first specialization Modifier<Base>
in full (or write it in a general form without any template specialization), and then somehow "add" the method prev()
to a specialization of the template class Modifier<Derived>
?我可以完整地写下第一个特化Modifier<Base>
(或以没有任何模板特化的通用形式编写它),然后以某种方式将方法prev()
“添加”到模板类Modifier<Derived>
的特化中吗?
I tried to do this by making Modifier<Derived>
inherit from both Derived
and Modifier<Base>
and using a virtual inheritance, but this results in a rather ugly diamond inheritance diagram, with duplicated obj
member variables of two different types, and is not really what I want: the two template specializations do not need to inherit from one another, they just need to implement the same behaviour for next()
.我试图通过使Modifier<Derived>
从Derived
和Modifier<Base>
继承并使用虚拟继承来做到这一点,但这会导致一个相当难看的菱形继承图,其中包含两种不同类型的重复obj
成员变量,并且不是真的是我想要的:这两个模板特化不需要相互继承,它们只需要为next()
实现相同的行为。
Thanks in advance for any suggestions.在此先感谢您的任何建议。
This all sounds a bit too tricksy for me - I would just make k
a member of Base
and have done with it - but if you really want to do it this way then simple template inheritance (aka static polymorphism) will do the job.这一切对我来说听起来有点太棘手了——我只会让k
成为Base
的成员并完成它——但如果你真的想这样做,那么简单的模板继承(又名静态多态性)就可以完成这项工作。
So what I have done here is structured the Modifier templates into a class hierarchy and done away with them inheriting from the actual classes whose behaviour they are modifying, since that is what is messing you up.所以我在这里所做的是将修饰符模板结构化为一个类层次结构,并取消它们从它们正在修改其行为的实际类继承,因为这会让你感到困惑。 And when you do that, this is what you end up with:当你这样做时,这就是你最终的结果:
template<class BaseOrDerived> class Modifier;
template<class BaseOrDerived> class ModifierCommon{
friend class Modifier<Derived>;
const BaseOrDerived& obj;
const int k;
public:
ModifierCommon(const BaseOrDerived& _obj, int _k) : obj(_obj), k(_k) {}
virtual int next(int x) const { return obj.next(x)+k; }
};
template<> class Modifier<Base>: public ModifierCommon<Base> {
using ModifierCommon<Base>::ModifierCommon;
};
template<> class Modifier<Derived>: public ModifierCommon<Derived> {
using ModifierCommon<Derived>::ModifierCommon;
public:
virtual int prev(int x) const { return obj.prev(x)-k; }
};
And that's all there is to it, best of luck.这就是它的全部内容,祝你好运。 But, as I say, personally I wouldn't do it at all, you're just over-egging the pudding.但是,正如我所说,就我个人而言,我根本不会这样做,你只是把布丁炒得过火了。
Hokay, as per the comments the OP has moved the goalposts a bit so let's see what we can do.好吧,根据评论,OP已经稍微移动了球门柱,所以让我们看看我们能做些什么。
To be able to access, for example, Modifier<Base>
as if (more or less) it was a true Base
object, you can add a couple of tweaks to the ModifierCommon
template as follows:例如,为了能够访问Modifier<Base>
,就好像(或多或少)它是一个真正的Base
对象一样,您可以向ModifierCommon
模板添加一些调整,如下所示:
template<class BaseOrDerived> class ModifierCommon{
...
public:
// Add these
BaseOrDerived* operator->() { return &this->obj; }
const BaseOrDerived* operator->() const { return &this->obj; }
operator BaseOrDerived& () const { return this->obj; }
// End add these
...
};
So, after taking out a couple of const
s, the whole thing now becomes:所以,在取出几个const
之后,整个事情现在变成了:
template<class BaseOrDerived> class ModifierCommon{
friend class Modifier<Derived>;
BaseOrDerived& obj;
const int k;
public:
ModifierCommon(BaseOrDerived& _obj, int _k) : obj(_obj), k(_k) {}
BaseOrDerived* operator->() { return &this->obj; }
const BaseOrDerived* operator->() const { return &this->obj; }
operator BaseOrDerived& () const { return this->obj; }
virtual int next(int x) const { return obj.next(x)+k; }
};
And here's an example of how you might use it (I added a test method called foo
to Base
and another called bar
to Derived
):下面是一个如何使用它的示例(我在Base
中添加了一个名为foo
的测试方法,在Derived
中添加了另一个名为bar
的测试方法):
void call_me_using_base (Base &b) { }
void call_me_using_derived (Derived &d) { }
int main()
{
Base b;
std::cout << b.next (100) << "\n";
Modifier<Base> mb (b, 42);
std::cout << mb.next (100) << "\n";
std::cout << mb->foo (10) << "\n";
call_me_using_base (mb);
Derived d;
std::cout << d.next (100) << "\n";
std::cout << d.next (100) << "\n";
Modifier<Derived> md (d, 84);
std::cout << md.next (100) << "\n";
std::cout << md.prev (100) << "\n";
std::cout << md->bar (21) << "\n";
call_me_using_derived (md);
}
And no, I still wouldn't do this.不,我仍然不会这样做。 Design a proper class hierarchy like everybody else does.像其他人一样设计一个适当的类层次结构。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.