首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >标量、向量、张量的抽象基类

标量、向量、张量的抽象基类
EN

Stack Overflow用户
提问于 2014-07-05 11:28:04
回答 1查看 376关注 0票数 0

我想设计一个类PrimitiveType,它作为数学实体(如标量、向量、张量等)的抽象类,将它们存储在一个std::vector<PrimitiveType *> myVector中,通过它我可以迭代。例如,有两个相同大小的向量,比如myVector1myVector2,我想做一些类似的事情

代码语言:javascript
复制
for (size_t i = 0; i < myVector1.size(); i++)
     myVector1[i] += myVector2[i];

也不想关心我是在添加标量向量还是张量。到现在为止,我想到了

代码语言:javascript
复制
#include <algorithm>
#include <cstddef>
#include <iostream>

template<class T> class Scalar;

template<class T>
class PrimitiveType
{ 
    protected:
        size_t size_;
        T *value_;

    public:
        virtual ~PrimitiveType() = 0;
        PrimitiveType & operator+=(const PrimitiveType &primitiveType) 
        {
            for (size_t i = 0; i < size_; i++)
                value_[i] += primitiveType.value_[i]; 
            return *this;
        }
};

template<class T> PrimitiveType<T>::~PrimitiveType() {};

template<class T>
class Scalar : public PrimitiveType<T>
{
    using PrimitiveType<T>::size_;
    using PrimitiveType<T>::value_;

    public:
        Scalar(T value = 0.0) 
        { 
            size_ = 1; 
            value_ = new T(value); 
        }
        ~Scalar() { delete value_; }
        operator T &() { return *value_; }
};

template<class T>
class Vector : public PrimitiveType<T>
{
    using PrimitiveType<T>::size_;
    using PrimitiveType<T>::value_;

    public:
        Vector(T value = 0.0) 
        { 
            size_ = 3; 
            value_ = new T[size_]; 
            std::fill(value_, size_, value); 
        }
        ~Vector() { delete[] value_; }
        T & operator()(size_t index) { return value_[index]; }
};

int main()
{   
    Scalar<double> s(3.2);
    std::cout << s << std::endl;

    static const size_t size = 3;

    std::vector<PrimitiveType<double> *> p = std::vector<PrimitiveType<double> *>(size);
    for (size_t i = 0; i < size; i++)
    {
        p[i] = new Scalar<double>();
        *(p[i]) += s;
        std::cout << *static_cast<Scalar<double> *>(p[i]) << std::endl;
    }
}

但我不认为这是一个非常干净的解决方案。特别地,

1)我希望能够在子类中使用初始化程序列表,但是在查找相关名称时会出现问题。

错误:“使用PrimitiveType::size_”不是“标量”的非静态数据成员。

如何实现像Scalar(T value = 0.0) : size_(1) , value_(new T(value)) {}这样的东西

2)我实际上更喜欢将value_变成一个静态数组,因为在编译时,我知道value_对于ScalarVector、.当然,这不适用于PrimitiveType,但是,PrimitiveType的实例从未被创建过。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-07-05 11:33:44

编辑:完成编辑,因为其他解决方案不合适。

那么,解决问题的最简单的方法是将存储从主类移到基类,并提供元素的访问器:

代码语言:javascript
复制
template <class C>
class PrimitiveType {
public:
    PrimitiveType & operator+=(const PrimitiveType &primitiveType) {
        if (this->_size() != primitiveType._size()) {
            throw "Incompatible type." ;
        }
        for (size_t i = 0 ; i < this->_size() ; ++i) {
            this->_get(i) += primitiveType._get(i) ;
        }
        return *this ;
    }
protected:
    virtual C& _get (size_t) = 0 ;
    virtual C _get(size_t) const = 0 ;
    virtual size_t _size () const = 0 ;
};

然后在ScalarVector中,例如:

代码语言:javascript
复制
template <class C>
class Scalar : PrimitiveType <C> {
    C _value ;
public:
    Scalar (C const& c) : _value(c) { }
protected:
    virtual C& _get (size_t) = 0 { return _value ; }
    virtual C _get(size_t) const = 0 { return _value ; }
    virtual size_t _size () const = 0 { return 1 ; }
};

template <class C, int N = 3>
class Vector : PrimitiveType <C> {
    std::array <C, N> _values ;
public:
    Scalar (std::initializer_list <C> l) : _values(l) { }
protected:
    virtual C& _get (size_t i) = 0 { return _values(i) ; }
    virtual C _get(size_t i) const = 0 { return _values(i) ; }
    virtual size_t _size () const = 0 { return _values.size() ; }
};

编辑的结束.

对于第一个问题,只需在PrimitiveType中添加一个受保护的构造函数,并从您的子类调用它:

代码语言:javascript
复制
class PrimitiveType {
protected:
    PrimitiveType (/* */) : _values(/* */), /* ... */ { }
};

class Scalar {
public:
    Scalar (/* */) : PrimitiveType(/* */) { }
}

对于第二个问题,添加一个存储类型作为第二个原始类型的参数模板:

代码语言:javascript
复制
template <class C, class S = std::vector <C>>
class PrimitiveType { /* */ }

template <class C>
class Scalar : public PrimitiveType <C, std::array <C, 1>> { /* */ }

已删除的例子:

代码语言:javascript
复制
template <class C, class S = std::vector <C>>
class PrimitiveType {
public:
    PrimitiveType & operator+=(const PrimitiveType &primitiveType) {
        /** Same code as yours. **/
    }

protected:
    S _values ;
    PrimitiveType (std::initializer_list <C> l) : _values(l) { }
};

template <class C>
class Scalar : public PrimitiveType <C, std::array <C, 1>> {
public:
    Scalar (C const& c) : PrimitiveType({c}) { }
};
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24585927

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档