运行时多态性C ++ 11和操作符重载

问题描述 投票:0回答:2

比方说,我想实现一些数学向量类。

为矢量界面会在多个地方被使用:基于阵列矢量,矩阵返回列和行作为矢量接口对象等。

我想重载+, - 运营商为我的向量。每个运营商应该返回一些载体实现类的新构造的对象。

但是,您知道运算符重载应返回一个值或引用。我不能返回一个值,因为我需要运行时多态性,所以我留下引用。但有函数调用对象应在堆上创建后不会死的参考。

所以,我应该如何处理这种情况?

附:我可以创建一个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;
    }
};
c++11 polymorphism operator-overloading run-time-polymorphism
2个回答
1
投票

我建议稍微修改设计用于容纳实施的多形态性质。

  1. 不要让vector多态性。
  2. 使用Data类包含vector实施的具体细节。
  3. Data多态性。

这将允许您通过值或引用,返回vectors作为适当的接口。


0
投票

通过多态性亚型是不能解决所有问题。我明白了什么是你想这样做,但我完全不明白为什么一个多态的模板解决方案是不够的,你需要有虚拟运营商(其中完全不与多态性的亚型拌匀)。

你要能够定义的混合类型的载体操作,这样就可以计算出真正的容器和代理容器之间的结果。

这首先应该要求您有需要,一个代理矩阵列是不是一个真正的容器,而是一个容器的视图,因此将他们两个人应该返回一个真正的容器(基本final类型如:一容器由实际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元件的一般容器的模板的方法。该代码假定这些类型的容器提供beginend方法,返回一个迭代器(这是在任何情况下,一个聪明的选择,因为它与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载体。

© www.soinside.com 2019 - 2024. All rights reserved.