[英]C++ Overload index operator for more than one array/vector
我不是高级程序员。 如何为具有两个(或更多)数组/向量类型变量的类重载[]
运算符?
class X
{
protected:
std::vector<double> m_x, m_y;
public:
double& operator[](const short &i) { return ???; }
};
我应该用于???
,或者我该怎么做(也许添加其他定义?)以能够调用任一变量?
附加问题:这将允许class derived : public X
其他类类型的class derived : public X
访问m_x
和m_y
进行编写吗?
更新:
谢谢所有回答的人,但恐怕如果我划定界线,那么第一个问题的答案为否,第二个问题的答案为是。 较长的版本意味着额外的struct
或class
或普通的setters / getters,我想通过对所有人使用简单的函数来避免这种情况。
就目前而言,当前的解决方案是在每个类中对每个变量的(临时)引用,以避免多余的X::
键入(并保持代码清晰),因为m_x
已经存在,一种或另一种方式。
您可以为此编写一个函数,例如:
double &get(unsigned int whichVector, unsigned int index)
{
return (whichVector == 0 ? m_x[index] : m_y[index]);
}
或使用operator():
struct A
{
std::vector<int> a1;
std::vector<int> a2;
int operator()(int vec, int index)
{
return (vec == 0 ? a1[index] : a2[index]);
}
};
A a;
auto var = a(0, 1);
但这仍然有点奇怪:)可能您应该只在外部提供const ref,例如:
const std::vector<double> &getX() const { return m_x; }
第二个问题:受保护的人将在公共继承中转换为私有(孩子/派生将有权使用这些成员)
您可以返回一个具有两个double的结构
struct A{
double& x;
double& y;
A(A& r) : x(r.x), y(r.y){}
A(double& x, double& y) : x(x), y(y){}
};
class X
{
protected:
std::vector<double> m_x, m_y;
public:
A operator[](const short &i) {
A result(m_x[i], m_y[i]);
return result;
}
};
感谢您编辑@marcinj
如果使用mixin不会让您感到不舒服,则可以使用标签分发,例如:
#include <utility>
#include <vector>
#include <iostream>
template <size_t I>
struct IndexedVector {
std::vector<double> v;
IndexedVector():v(10){}
};
template <size_t I>
struct tag {
int i;
};
template <size_t S, class = std::make_index_sequence<S>>
struct MixinVector;
template <size_t S, size_t... Is>
struct MixinVector<S, std::index_sequence<Is...>>: IndexedVector<Is>... {
template <size_t I>
double &operator[](tag<I> i) {
return IndexedVector<I>::v[i.i];
}
};
int main() {
MixinVector<2> mv;
mv[tag<0>{0}] = 1.0;
std::cout << mv[tag<0>{0}] << std::endl;
}
要使用std::index_sequence
您需要支持c ++ 14的编译器(尽管您可以在c ++ 11中自己实现)。 通过简单的MixinVector
模板参数修改,该方法可以轻松扩展为任意数量的向量。
假设您要针对相同的参数和单个返回值对m_x
和m_y
索引:
struct XGetter
{
double& x;
double& y;
};
XGetter operator[](const short &i) { return { m_x[i], m_y[i] }; }
和const
重载:
struct XGetterReadOnly
{
double x;
double y;
};
XGetterReadOnly operator[](const short &i) const { return { m_x[i], m_y[i] }; }
编译器将很好地优化中间类XGetter
和XGetterReadOnly
,如果您是C ++的XGetter
, XGetterReadOnly
这些中间类可能很难XGetterReadOnly
。
在概念和设计层面都有很多坏的东西。
您是否可以同时针对两个截然不同的事物? 没有? 这就是为什么您不能使用一个索引来解决两个不同的向量并保持它们的区别的原因。
您可以做很多事情:从语法角度来看,“组合”两个值int的任何方法都是好的:
return m_x[i]+m_y[x]
或return sin(m_x[i])*cos(m_y[i])
或return whatever_complicated_expression_you_like_much
return sin(m_x[i])*cos(m_y[i])
但是那是什么意思呢? 关键是为什么您的班级有两个矢量? 您希望他们代表什么? 您是什么意思(象征性地)将它们都编入索引?
我可以做的就是保持他们的区别
auto operator[](int i) const
{ return std::make_pair(m_x[i],m_y[i]); }
这样就得到了一个std::pair<double,double>
其fist
和second
成员分别是m_x [i]和m_y [i]。
或者...您可以return std::vector<double>{m_x[i],m_y[i]};
关于另一个问题:是的,作为公共继承使新类能够访问受保护的部分:这就是受保护的目的。
是的,您是R / W:公开,受保护和私有是可见性,而不是可读性和可写性。 这就是const的含义。
再说一遍:您的班级代表什么? 没有此类信息,我们将无法确定什么才是有意义的。
好的,发表您的评论:
您需要两种不同的功能:一种用于读取( double operator[](unsigned) const
),另一种用于写入( double& operator[](unsigned) const
)
如果您知道向量的长度是已知的(例如200),则可以编写i / 1000这样的同义变换来标识向量,并通过i%1000来编码以得到索引,这样0..199的值就等于1000。 1199指向第二个2000..2199指向第三个...等等
或者...您可以使用std::pair<unsigned,unsigend>
作为索引( like operator[](const std::pair<unsigned,unsigned>& i)
,使用i.first标识向量,然后i.second索引到它,然后调用x [{1,10}],x [{3,30}]等。
或者...您可以将vetor链接在一起
if(i<m_x.size()) return m_x[i]; i-=m_x:size();
if(i<m_y.size()) return m_y[i]; i-=m_y:size();
if(i<m_z.size()) return m_z[i]; i-=m_z:size();
...
这样您就可以连续索引它们。
但是您可以使用向量数组而不是不同的向量变量来获得更多算法解决方案
如果您有std::array<std::vector<double>,N> m;
上面的代码可以代替m_x,m_y和m_z ...
for(auto& v: m)
{
if(i<v.size()) return v[i];
i-=v.size();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.