c++ - 带有纯虚函数的模板类的 C++ 实现
问题描述
我正在开发一个必须能够处理不同类型数据(最终甚至不是数学数据)的计算器,但我被困在Complex
数字类的实现中。这是我想要实现的目标:
- 一个被调用的抽象模板类
vectorSpace
,我将从中派生出其他具体类,如Complex
数字、Vector等。
为什么我要这样创建它?好吧,所有向量空间的唯一共同特征是它们允许两种运算:对相同类型的空间进行求和运算,以及在同一字段中进行点积(或标量积?不确定英文的实际名称)。该字段可能是非常不同的类型(整数、双精度、字符串等),所以我想用一个模板来制作它。然后每个派生类都会将字段的数据类型指定给模板并实现虚拟操作
Complex
派生自的派生类,将vectorSpace
double 指定为数据类型,定义sum和dot product的操作,然后添加所有其余的可用操作。
这是我此刻的vectorSpace
课程代码(完全写在 .h 文件中):
#ifndef VECTORSPACE_H
#define VECTORSPACE_H
template <class T>
class vectorSpace
{
public:
virtual vectorSpace<T>& sum(const vectorSpace<T>&) const =0;
virtual vectorSpace<T>& dotProduct(const T&) const =0;
};
#endif // VECTORSPACE_H
在 complex.h 我有这个:
#ifndef COMPLEX_H
#define COMPLEX_H
#include "vectorspace.h"
class Complex : public vectorSpace<double> {
private:
double re, im;
public:
Complex(double r=0, double i=0);
double real() const;
double imag() const;
Complex& operator +(const Complex& z) const;
Complex& sum(const Complex& z) const;
Complex& operator *(double d) const;
Complex dotProduct(double d) const;
//other functions for Complex
};
#endif // COMPLEX_H
最后是我完成的实现:
#include "complex.h"
Complex::Complex(double r, double i) : re(r), im(i) {}
double Complex::real() const{
return re;
}
double Complex::imag() const{
return im;
}
Complex& Complex::operator +(const Complex& z) const{
Complex *aux = new Complex(); //new is not allowed for an abstract class but it should not be abstract anymore
aux->re = re + z->re;
aux->im = im + z->im;
return *aux;
}
Complex& Complex::sum(const Complex &z) const{
return *this + z;
}
/* I've tried even with this, but it does not work!!
vectorSpace<double>& Complex:sum(const vectorSpace<double>& z) const{
return *this + z;
}
*/
Complex Complex::operator *(double d) const{
Complex aux;
aux.re = re * d;
aux.im = im * d;
return aux;
}
Complex& Complex::dotProduct(const double& d) const{
return *this * d;
}
这只是我所做的最后一次实施尝试。我尝试了各种组合,但我仍然无法让我的Complex
班级将其识别为具体而不是抽象。我在哪里做错了?
解决方案
问题:
您需要vectorSpace
在具体派生类中覆盖抽象模板类的以下纯虚拟成员方法Complex
:
virtual vectorSpace<T>& sum(const vectorSpace<T>&) const = 0;
virtual vectorSpace<T>& dotProduct(const T&) const = 0;
override
目前,您提供了两个重载的成员方法,但由于使用了不同的返回类型(即Complex&
!= ),这些方法没有被覆盖(在将关键字添加到这两个成员方法后尝试编译vectorSpace<double>&
):
Complex& Complex::sum(const Complex &z) const {
return *this + z;
}
Complex& Complex::dotProduct(const double& d) const {
return *this * d;
}
一个可能的解决方案:
Complex
作为附加模板参数传递给基类vectorSpace
。使用此附加模板参数的类型更改纯虚拟成员方法的签名。
一种可能的实现[在线试用]:
template< typename T, typename ValueT >
class VectorSpace {
public:
virtual const ValueT sum(const ValueT&) const noexcept = 0;
virtual const ValueT dotProduct(T) const noexcept = 0;
};
class Complex : public VectorSpace< double, Complex > {
private:
double re, im;
public:
Complex(double r, double i) noexcept
: re(r), im(i) {}
// Do not worry about the const return values;
// C++17's Guaranteed Copy Elision will take care of that.
const Complex operator+(const Complex& z) const noexcept {
return Complex(re + z.re, im + z.im);
}
const Complex operator*(double d) const noexcept {
return Complex(re * d, im * d);
}
const Complex sum(const Complex& z) const noexcept override {
return *this + z;
}
const Complex dotProduct(double d) const noexcept override {
// Note that this is not a general dot or inner product.
// This is just scalar multiplication.
return *this * d;
}
};
int main() {
Complex c(1.0, 2.0); // As concrete as can be ;-)
return 0;
}
我做了一些更改,因为您的堆分配是纯粹的开销和危险的,并且您不能const
使用该实例的成员方法将非引用传递给该实例const
,除非您真的想滥用 a const_cast
)。
推荐阅读
- javascript - 尝试在没有 OpenGL 的情况下用 Java 制作立方体
- javascript - 我可以将属性(或某种等价物)分配给 Javascript 变量吗?包含示例代码
- backend - 我应该如何制作 URL 路由器?
- php - 从用希伯来语编写的 vbulletin 数据库获取数据,得到奇怪的编码
- tensorflow - 当我在新的自定义 C++ 操作中调用标准操作(例如 MatMul)时,Bazel 返回错误
- sql - WITH clause sub-query has non-unique column names
- isis - Apache isis - 更改欢迎页面
- acumatica - 发布文档后如何创建额外的日记帐分录?
- elasticsearch - 如何使用 Python 的 elasticsearch_dsl 搜索对脚本字段求和?
- c# - 从任务\线程中的代码更改 ui 值