派生模板重写成员函数 C++ 的返回类型
我正在编写矩阵类。看一下这个定义:
template <typename T, unsigned int dimension_x, unsigned int dimension_y>
class generic_matrix
{
...
generic_matrix<T, dimension_x - 1, dimension_y - 1>
minor(unsigned int x, unsigned int y) const
{ ... }
...
}
template <typename T, unsigned int dimension>
class generic_square_matrix : public generic_matrix<T, dimension, dimension>
{
...
generic_square_matrix(const generic_matrix<T, dimension, dimension>& other)
{ ... }
...
void foo();
}
generic_square_matrix 类提供了矩阵乘法等附加函数。 这样做没有问题:
generic_square_matrix<T, 4> m = generic_matrix<T, 4, 4>();
由于构造函数的原因,即使类型不是 generic_square_matrix,也可以将任何方阵分配给 M。这是可能的,因为数据不会在子级之间发生变化,只有支持的函数会发生变化。这也是可能的:
generic_square_matrix<T, 4> m = generic_square_matrix<T, 5>().minor(1,1);
此处适用相同的转换。但现在问题来了:
generic_square_matrix<T, 4>().minor(1,1).foo(); //problem, foo is not in generic_matrix<T, 3, 3>
为了解决这个问题,我希望 generic_square_matrix::minor 返回 generic_square_matrix 而不是 generic_matrix。我认为唯一可能的方法是使用模板专业化。但由于专业化基本上被视为一个单独的类,因此我必须重新定义所有函数。我无法像调用派生类那样调用非专用类的函数,因此我必须复制整个函数。 这不是一个非常好的通用编程解决方案,并且需要大量工作。
C++ 几乎可以解决我的问题:派生类的虚函数可以返回指向与基类返回的不同类的指针或引用,如果该类是从基类返回的类派生的。 generic_square_matrix 派生自 generic_matrix,但该函数不返回指针或引用,因此这不适用于此处。
这个问题有解决方案吗(可能涉及完全其他的结构;我唯一的要求是尺寸是模板参数并且方阵可以具有附加功能)。
预先感谢,
路德
I am writing matrix classes. Take a look at this definition:
template <typename T, unsigned int dimension_x, unsigned int dimension_y>
class generic_matrix
{
...
generic_matrix<T, dimension_x - 1, dimension_y - 1>
minor(unsigned int x, unsigned int y) const
{ ... }
...
}
template <typename T, unsigned int dimension>
class generic_square_matrix : public generic_matrix<T, dimension, dimension>
{
...
generic_square_matrix(const generic_matrix<T, dimension, dimension>& other)
{ ... }
...
void foo();
}
The generic_square_matrix class provides additional functions like matrix multiplication.
Doing this is no problem:
generic_square_matrix<T, 4> m = generic_matrix<T, 4, 4>();
It is possible to assign any square matrix to M, even though the type is not generic_square_matrix, due to the constructor. This is possible because the data does not change across children, only the supported functions. This is also possible:
generic_square_matrix<T, 4> m = generic_square_matrix<T, 5>().minor(1,1);
Same conversion applies here. But now comes the problem:
generic_square_matrix<T, 4>().minor(1,1).foo(); //problem, foo is not in generic_matrix<T, 3, 3>
To solve this I would like generic_square_matrix::minor to return a generic_square_matrix instead of a generic_matrix. The only possible way to do this, I think is to use template specialisation. But since a specialisation is basically treated like a separate class, I have to redefine all functions. I cannot call the function of the non-specialised class as you would do with a derived class, so I have to copy the entire function.
This is not a very nice generic-programming solution, and a lot of work.
C++ almost has a solution for my problem: a virtual function of a derived class, can return a pointer or reference to a different class than the base class returns, if this class is derived from the class that the base class returns. generic_square_matrix is derived from generic_matrix, but the function does not return a pointer nor reference, so this doesn't apply here.
Is there a solution to this problem (possibly involving an entirely other structure; my only requirements are that the dimensions are a template parameter and that square matrices can have additional functionality).
Thanks in advance,
Ruud
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您可以只在派生类中实现该函数,而不将其设为虚拟。这将“隐藏”基类实现,并且可能适合您使用,尽管人们普遍厌恶隐藏成员函数。
更好的方法可能是使用不同的名称,尽管这可能会破坏界面的“纯度”。
最后,minor() 可以作为自由函数而不是成员函数来实现吗?然后您可以根据需要提供重载,并且将在编译时调用正确的函数。这是最接近我打开的隐藏案例的方法,但我怀疑它会被更普遍地接受为“良好实践”。
You could just implement the function in the derived class without making it virtual. This will "hide" the base class implementation and may be desirable for your use despite the general aversion to hiding member functions.
A better method might be to just use a different name, although that may upset the "purity" of your interface.
Finally- could minor() be implemented as a free function instead of a member function? Then you could provide overloads as appropriate, and the correct function would be called at compile time. This is the closest to the method hiding case I opened with, but I suspect it would be more generally accepted as "good practice."
如果您可以简单地使
minor()
成为一个自由函数,则无需使设计复杂化:...然后您可以根据需要添加替代版本。
There is no need for complicating the design if you can simply make
minor()
a free function:... then you can add alternative versions as much as you want.
如果您不以多态方式使用这些类型,则只需非虚拟地重写派生类中的基类方法,以便它返回派生类对象。它会隐藏基类版本,这通常是不需要的,但在您的情况下似乎是这样。
或者,您可以将这些成员函数设为自由函数模板,如有必要,可以对不同类型的矩阵进行重载。 (尽管模板化可能会自动解决这个问题。)
If you don't use these types polymorphically, you could just override the base class method in the derived class non-virtually so that it returns a derived class object. It would hide the base class version, which usually isn't wanted, but in your case it seems it is.
Or you make these member functions free function templates, if necessary with overloads for different types of matrices. (Although templatization might take care of that automatically.)
模板专业化将起作用。您要做的就是获取共享代码并将其放入基类中,然后从两者继承。保护基础中的析构函数,以便没有人可以通过强制转换到基础并尝试删除它来破坏您的概念。
类似这样:
还有其他方法,但这是最简单的方法之一。
Template specialization will work. What you do is take the shared code and put it in a base class and then just inherit from both. Protect the destructor in the base so that nobody can break your concept by casting to the base and trying to delete it.
Something like so:
There are other ways, but that's one of the easiest.