假设我正在尝试实现一些数学向量类。
作为向量接口将在多个地方使用:基于数组的向量,矩阵作为向量接口对象返回列和行等。
我想为我的向量重载+,-运算符。每个运算符都应该返回某个向量实现类的新构造对象。
但正如你所知道的,操作符重载应该返回值或引用。我不能返回值,因为我需要运行时多态性,所以我只能使用引用。但是为了有一个在函数调用后不会死的引用,应该在堆中创建对象。
那么,我应该如何管理这种情况呢?
附注:我可以创建一个shared_ptr并返回一个包含值的引用,但这看起来不是一个好的做法。
typedef unsigned int vector_idx_t;
template <class T, vector_idx_t size>
class vector {
public:
virtual ~vector();
virtual T& operator[](const vector_idx_t idx) = 0;
virtual vector<T, size>& operator+ (const T& a) const = 0;
virtual vector<T, size>& operator- (const T& a) const = 0;
virtual vector<T, size>& operator* (const T& a) const = 0;
virtual vector<T, size>& operator/ (const T& a) const = 0;
virtual vector<T, size>& operator+ (const vector<T, size>& vec2) const = 0;
virtual vector<T, size>& operator- (const vector<T, size>& vec2) const = 0;
};
template <class T, vector_idx_t size>
class array_vector: public vector<T, size> {
private:
std::array<T, size> m_elements;
public:
array_vector();
array_vector(std::array<T, size> elements);
array_vector(const vector<T, size>& vec2);
array_vector(std::initializer_list<T> elems);
virtual ~array_vector();
virtual T& operator[](const vector_idx_t idx) {
return m_elements[idx];
}
virtual vector<T, size>& operator+ (const T& a) const {
std::array<T, size> e;
for (vector_idx_t i = 0; i < size; ++i) {
e[i] = m_elements[i] + a;
}
auto v = std::make_shared<array_vector<T, size>>(elems);
return *v;
}
};发布于 2019-02-12 01:03:48
我建议对您的设计稍作修改,以适应实现的多态特性。
在包含vector.
实现特定详细信息的情况下,不要使
vector Data类这将允许您按值或按引用将vector返回给接口。
发布于 2019-02-12 01:41:52
子类型的多态性并不是解决所有问题的答案。我知道你想做什么,但我不太明白为什么按模板多态解决方案是不够的,你需要有虚拟运算符(它根本不能很好地与按子类型的多态混合)。
您希望能够在混合类型的向量上定义操作,以便可以计算真实容器和容器代理之间的结果。
这首先应该要求你有一个你需要的基本的最终类型,一个矩阵列的代理不是一个真正的容器,而是一个容器的视图,所以添加其中的两个应该返回一个真正的容器(例如。由实际的std::array支持的容器?)。
类似的设计可以通过如下方式进行管理
template<typename ContainerType, typename ElementType>
class vector_of : public ContainerType
{
public:
vector_of(const ContainerType& container) : ContainerType(container) { }
vector_of<ContainerType, ElementType> operator+(const ElementType& a) const
{
vector_of<ContainerType, ElementType> copy = vector_of<ContainerType,ElementType>(*this);
std::for_each(copy.begin(), copy.end(), [&a](ElementType& element) { element += a; });
}
template<typename T>
vector_of<ContainerType, ElementType> operator+(const vector_of<T, ElementType>& a) const
{
vector_of<ContainerType, ElementType> copy(*this);
auto it = copy.begin();
auto it2 = a.begin();
while (it != copy.end() && it2 != a.end())
{
*it += *it2;
++it;
++it2;
}
return copy;
}
};这里的诀窍是operator+是一个接受ElementType元素的泛型容器的模板方法。代码假设这些类型的容器提供了返回迭代器的begin和end方法(这在任何情况下都是一个明智的选择,因为它可以很好地与STL一起工作)。
使用您可以执行以下操作:
class MatrixRowProxy
{
private:
int* data;
size_t length;
public:
MatrixRowProxy(int* data, size_t length) : data(data), length(length) { }
int* begin() const { return data; }
int* end() const { return data + length; }
};
vector_of<std::array<int, 5>, int> base = vector_of<std::array<int, 5>, int>({ 1, 2, 3, 4, 5 });
vector_of<std::vector<int>, int> element = vector_of<std::vector<int>, int>({ 2, 3, 4, 5, 6 });
int* data = new int[5] { 10, 20, 30, 40, 50};
vector_of<MatrixRowProxy, int> proxy = vector_of<MatrixRowProxy, int>(MatrixRowProxy(data, 5));
auto result = base + element + proxy;
for (const auto& t : result)
std::cout << t << std::endl;所以你可以添加不同种类的向量,而不需要任何virtual方法。
当然,这些方法需要在方法中创建一个新的结果对象。这是通过将其复制到新的vector_of<ContainerType, ElementType>中来完成的。没有什么可以阻止你添加第三个模板参数,比如VectorFactory,它负责这一点,这样你就可以使用矢量,它也是这些运算符的LHS上的包装器。
https://stackoverflow.com/questions/54635065
复制相似问题