[英]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.