我想设计一个类PrimitiveType,它作为数学实体(如标量、向量、张量等)的抽象类,将它们存储在一个std::vector<PrimitiveType *> myVector中,通过它我可以迭代。例如,有两个相同大小的向量,比如myVector1和myVector2,我想做一些类似的事情
for (size_t i = 0; i < myVector1.size(); i++)
myVector1[i] += myVector2[i];也不想关心我是在添加标量向量还是张量。到现在为止,我想到了
#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_对于Scalar、Vector、.当然,这不适用于PrimitiveType,但是,PrimitiveType的实例从未被创建过。
发布于 2014-07-05 11:33:44
编辑:完成编辑,因为其他解决方案不合适。
那么,解决问题的最简单的方法是将存储从主类移到基类,并提供元素的访问器:
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 ;
};然后在Scalar和Vector中,例如:
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中添加一个受保护的构造函数,并从您的子类调用它:
class PrimitiveType {
protected:
PrimitiveType (/* */) : _values(/* */), /* ... */ { }
};
class Scalar {
public:
Scalar (/* */) : PrimitiveType(/* */) { }
}对于第二个问题,添加一个存储类型作为第二个原始类型的参数模板:
template <class C, class S = std::vector <C>>
class PrimitiveType { /* */ }
template <class C>
class Scalar : public PrimitiveType <C, std::array <C, 1>> { /* */ }已删除的例子:
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}) { }
};https://stackoverflow.com/questions/24585927
复制相似问题