2016-08-17 9 views
0

私は高度なプログラマではありません。 2つ(またはそれ以上)の配列/ベクトル型変数を持つクラスに対して[]演算子をどのようにオーバーロードできますか?C++複数の配列/ベクトルのオーバーロードインデックス演算子

class X 
{ 
protected: 
    std::vector<double> m_x, m_y; 
public: 
    double& operator[](const short &i) { return ???; } 
}; 
(多分他の定義を追加する?)のいずれかの変数を呼び出すことができるように、私は ???のために使用すべきか、私はそれをどのように行うことができますどのような


その他の質問:他の種類のタイプのclass derived : public Xアクセスm_xm_yの書き込みが許可されますか?


UPDATE:

はあなたに答えみんなに感謝、私は、私はラインを描くならば、私の最初の質問への答えはノー、第二yesにあることを恐れています。より長いバージョンは、追加のstruct、またはclass、または単純なセッター/ゲッターのいずれかを意味します。
m_xはすでに存在していたので、現在の解決策は、各クラスの各変数の(X::の入力を省略してコードをクリアしないように)各変数の(一時的な)参照です。

+0

2つの別々のベクトルの代わりに 'std :: vector > 'を使用しないのはなぜですか? –

+2

1つの方法、1つの変数。コードの意味についての詳細を私たちに教えてください。さらに、追加の答えは*はい*です。 –

+0

@sorosh_sabzベクトルが3つ以上ある場合、私はどうしますか? #Biagio変数にアクセスするすべてのクラスに共通の変数を保持するインターフェイスクラスです。それらの数は定義されていません。つまり、時間が経つにつれて大きくなります。 –

答えて

0

あなたのような、このためだけの関数を書くことができます。

double &get(unsigned int whichVector, unsigned int index) 
{ 
    return (whichVector == 0 ? m_x[index] : m_y[index]); 
} 

または(演算子を使用):

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 outsideのように:

const std::vector<double> &getX() const { return m_x; } 

と第2の質問:保護された公開の継承でプライベートに変換されますLD /派生は、これらのmemebersにアクセスできるようになります)

0

あなたは、構造体は、ミックスインを使用すると、あなたはできるあなたが不快にしない場合は

+1

std :: pair を使うことができます。新しいクラス –

+0

@sorosh_sabzを書くと、2つ以上の変数があります。 std :: pairでを実行できますか? – burakozgul

+2

'std :: tuple'は明らかです。 – LogicStuff

0

を@marcinjする編集のための2つのダブル

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; 
    } 
}; 

感謝を持って返すことができます使用は、タグのようなディスパッチ:

#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; 
} 

あなたはしかし、(あなたががC++ 11でそれを自分で実装することができます)C++ 14を支持するコンパイラ必要std::index_sequence使用するには。テンプレートのパラメータを変更するだけで、任意の数のベクトルに簡単に拡張できます。MixinVector

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] }; } 

コンパイラは離れて最適化するのに良い仕事をするだろうあなたはm_xと同じパラメータと、単一の戻り値に対してインデックスさm_yをしたいと仮定すると、

+0

これは悪くはありませんが、ゲッター(x、i)の塗装版のようです。これまでのすべての答えは、それぞれが有効なポイントを提示していますが、最初は避けようとしていたコードがあまりにもふわふわしています。オーバーロードについては残念ですが、私は 'X :: m_x'などを使うことに頼るかもしれません。おそらくポインタやショートカットとしての参照かもしれません。 –

0

中間クラスXGetterXGetterReadOnlyあなたがC++を初めて使っている人なら、あなたの頭を丸くするのは難しいでしょう。

0

概念レベルとデザインレベルのどちらかに壊れたものがたくさんあります。

指を2つの異なるものに同時に指向させることはできますか?いいえ?そのため、1つの索引を使用して区別できる2つの異なるベクトルに対処することはできません。

あなたは多くのことを行うことができますどのような方法2つの値を「組み合わせる」するint型1は、ビューの構文の点で 良いです:

return m_x[i]+m_y[x]またはreturn sin(m_x[i])*cos(m_y[i])またはreturn whatever_complicated_expression_you_like_much

しかし、それの意味は何ですか?ポイントはあなたのクラスに2つのベクトルがあるのはなぜですか?何を表現してほしいですか?あなたは(意味的に)それらの両方を索引付けすることは何を意味しますか?私は彼らの区別を維持するために行うことができます

何かがあなたがstd::pair<double,double>そのfistsecondメンバーがm_x [i]とm_y [i]をそれぞれ取得すること

auto operator[](int i) const 
{ return std::make_pair(m_x[i],m_y[i]); } 

そうです。

または...あなたが他の質問についてreturn std::vector<double>{m_x[i],m_y[i]};


をすることができます:はい、パブリックとして継承して保護された部分にアクセスすることができる新しいクラスを作る:それは何のためにあるのか、保護です。

はい、あなたはR/W:public、protected、privateは可視性であり、可読性と書き込み性はありません。それがconstの意味です。

もう一度:あなたのクラスは何を表していますか?そのような情報がなければ、私たちは何が意味を成立させることができないのか、何ができないのかを確立することはできませ


[OK]を、あなたのコメントを次のように述べています

あなたは二つの異なるfuncntions必要があります:あなたはベクトルが既知の長さ-sayを知っている場合は、読み取りのための1(double operator[](unsigned) const)と書き込み用(double& operator[](unsigned) const

を200、あなたはベクトルを識別するためにi/1000のようなidex変換をコード化することができ、インデックスを取得するためにi%1000を使用することができる.0.199 addres最初、1000..1199 address第2の2000..2199 address 3番目など...

または...インデックスとしてstd::pair<unsigned,unsigend>を使用できます(like operator[](const std::pair<unsigned,unsigned>& i)、i.firstを使用してベクトルを識別し、i.secondを使用してインデックスを作成した後、x [{1,10}]、x [{3,30}]など) 。

または...あなたがそうあなたのインデックスにそれらその連続

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(); 
... 

として一緒に連鎖vetorことができます。

しかし、あなたが代わりにm_x、m_yとm_z上記のコードのstd::array<std::vector<double>,N> m;ができる持っている場合は、ベクトルの配列の代わりに、個別のベクトル変数

を使用して、よりアルゴリズム的な解決策を得ることができます...

for(auto& v: m) 
{ 
    if(i<v.size()) return v[i]; 
    i-=v.size(); 
} 
+0

2つ以上のベクトルがあり、それらはデータの累積を表し、したがって計算に応じて変化する。これらの計算は、外部の派生クラス、各クラス(例えば、実際のケースではない)、湿度、温度などによって行われ、派生クラスの数はさまざまです(私は風速や高度を加えることができます。 )。そして、私は長い 'Class :: getX(i)'と 'Class:setX(var、i)'を使用するのではなく、変数の読み込み/書き込みアクセスを高速にするために '[]'をオーバーロードしたかったのです。 –

+0

@aconcernedcitizenはアップデートを見る –

関連する問題