简体   繁体   English

包含纯虚函数的模板类的C ++实现

[英]C++ implementation of template class with pure virtual functions in it

I'm working on a calculator that has to be able to work on different types of data (even not math data, eventually) but I'm stuck in the implementation of the Complex number class. 我正在使用一个必须能够处理不同类型的数据(最终甚至不是数学数据)的计算器,但是我仍然坚持执行Complex类。 Here is what I want to achieve: 这是我要实现的目标:

  • An abstract template class called vectorSpace from which I will derive other concrete classes like Complex numbers, Vector s, and so on. 抽象模板类称为vectorSpace ,我将从中抽象出其他具体类,例如ComplexVector等等。

Why do I want to create it like this? 我为什么要这样创建它? Well, the only common characteristic of ALL the vector spaces is that they allow two operations: sum operation with the same type of space, and dot product (or scalar product ? Not sure of the actual name in English) in the same field. 好吧, 所有向量空间的唯一共同特征是它们允许两个运算:相同空间类型的求和运算,以及同一字段中的点积 (或标量积 ?不确定英文的实际名称)。 The field could be of very different types ( integer , double , strings , etc) so I want to make it with a template . 该字段的类型可能非常不同( 整数双精度型字符串等),因此我想使用模板进行设置 Every derivative class will then specify the data type of the field to the template and implement the virtual operations 然后,每个派生类将为模板指定字段的数据类型并实现虚拟操作

  • A derivative class Complex that will derive from vectorSpace , specifying double as data type, defining the operations of sum and dot product , and then adding all the rest of the available operations. 派生类Complex ,它将从vectorSpace派生,将double指定为数据类型,定义sumdot product的运算,然后将所有其余可用运算相加。

This is my code in this moment for vectorSpace class (entirely written in a .h file): 这是我现在针对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

In complex.h I have this: 在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

and finally the implementation I've done: 最后是我完成的实现:

#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;
}

This is just the last implementation attempt I've done. 这只是我所做的最后一次实现尝试。 I've tried various combinations, but still I can't get my Complex class to get it recognized as concrete instead of abstract. 我尝试了各种组合,但是仍然无法获取Complex类以使其被识别为具体而非抽象。 Where do I am doing wrong? 我在哪里做错了?

The problem : 问题

You need to override the following pure virtual member methods of the abstract template class vectorSpace in your concrete derived class Complex : 您需要在您的具体派生类Complex重写抽象模板类vectorSpace的以下纯虚拟成员方法:

virtual vectorSpace<T>& sum(const vectorSpace<T>&) const = 0;
virtual vectorSpace<T>& dotProduct(const T&) const = 0;

Currently, you provide two overloaded member methods, but these are no overrides (try compiling after adding the override keyword to both of these member methods) due to the use of different return types (ie Complex& != vectorSpace<double>& ): 当前,您提供了两个重载的成员方法,但是由于使用了不同的返回类型(例如Complex& != vectorSpace<double>& ),它们没有被覆盖(在将override关键字添加到这两个成员方法之后尝试编译):

Complex& Complex::sum(const Complex &z) const {
    return *this + z;
}

Complex& Complex::dotProduct(const double& d) const {
    return *this * d;
}

A possible solution : 可能的解决方案

Pass Complex as an additional template parameter to the base class vectorSpace . Complex作为附加模板参数传递给基类vectorSpace Change the signature of the pure virtual member methods using this additional template parameter's type. 使用此附加模板参数的类型更改纯虚拟成员方法的签名。

A possible implementation [ Try It Online ]: 可能的实现 [ 在线试用 ]:

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;
}

I made a few changes, since your heap allocations are pure overhead and dangerous, and you cannot pass a non- const reference to an instance using a const member method of that instance unless you really want to misuse a const_cast ). 我做了一些更改,因为您的堆分配纯粹是开销和危险,并且除非您确实想滥用const_cast ,否则您无法使用该实例的const成员方法将非const引用传递给该实例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM