我不是高级程序员。如何为具有两个(或更多)数组/向量类型变量的类重载[]
运算符?
class X
{
protected:
std::vector<double> m_x, m_y;
public:
double& operator[](const short &i) { return ???; }
};
我应该为???
使用什么,或者我该怎么做(可能还要添加其他定义?)才能调用其中的任何变量?
其他问题:这是否允许其他类型的class derived : public X
类访问m_x
和m_y
进行撰写?
更新:
谢谢所有回答的人,但我担心如果我划清界线,那么第一个问题的答案就是否定,第二个答案是肯定的。较长的版本意味着额外的struct
或class
或普通的setter / getter,我想通过对所有人使用简单的函数来避免这种情况。
就目前而言,当前的解决方案是对每个变量的(临时)引用,在每个类中避免额外的X::
输入(并保持代码清晰),因为m_x
本来就存在,单向或另一个。
答案 0 :(得分:0)
你可以为此编写一个函数,例如:
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; }
和第二个问题:受保护将在公共继承中转换为私有(子/派生将有权访问这些成员)
答案 1 :(得分:0)
你可以返回一个结构有两个双
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
答案 2 :(得分:0)
如果使用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
模板参数修改,该方法可以轻松扩展到任意数量的向量。
答案 3 :(得分:0)
假设您希望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] }; }
如果你是C ++的新手,编译器会很好地优化掉适当的中间类XGetter
和XGetterReadOnly
,这可能很难让你理解。
答案 4 :(得分:0)
在概念和设计层面都有许多破碎的东西。
你是否能够同时指向两个截然不同的东西?没有?这就是为什么你不能使用一个索引来解决两个不同的向量来保持它们的区别。
你可以做很多事情:无论如何结合&#34;两个值int one是好的 从句法的角度来看:
return m_x[i]+m_y[x]
或return sin(m_x[i])*cos(m_y[i])
或return whatever_complicated_expression_you_like_much
但那是什么意思呢?关键是为什么你的课堂上有两个矢量?你想让他们代表什么?你是什么意思(语义上)索引他们两个?
我能做些什么来保持他们的区别
auto operator[](int i) const
{ return std::make_pair(m_x[i],m_y[i]); }
这样您就可以得到std::pair<double,double>
和fist
成员分别为m_x [i]和m_y [i]的second
。
或者......你可以return std::vector<double>{m_x[i],m_y[i]};
关于您的另一个问题:是的,继承为公开使新班级能够访问受保护的部分:这是受保护的内容。
是的,您可以使用R / W:public,protected和private是关于可见性,而不是可读性和可写性。这就是const的意思。
但是又一次:你的班级代表什么?没有这些信息,我们无法确定什么是有意义的,什么不是。
好的,陈述你的评论:
你需要两个不同的功能:一个用于读取(double operator[](unsigned) const
)而另一个用于写入(double& operator[](unsigned) const
)
如果你知道向量具有已知的长度--say 200-,你可以编码像i / 1000这样的idex transforamtion来识别向量而使用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();
}