スコープの階層化について
スコープの階層化について
C++のスコープについて困っています。
特定のメンバ関数のみで扱う変数があり、それをその関数内で宣言しました。
そのメンバ関数で新たに再帰処理が必要になったので、同じクラスの別メンバとして再帰関数を作りそれを呼び出すようにしたのですが、その関数では変数が参照できませんでした。
現状、引数として渡していますが、何度も呼び出される再帰関数なので非効率的で変だと思っています。
クラススコープの下に2つのメンバ関数で共有する変数をおくスコープがあれば上手くいく感じがしています。
こういった場合、スコープを階層化するにはどうしたらいいでしょうか?
特定のメンバ関数のみで扱う変数があり、それをその関数内で宣言しました。
そのメンバ関数で新たに再帰処理が必要になったので、同じクラスの別メンバとして再帰関数を作りそれを呼び出すようにしたのですが、その関数では変数が参照できませんでした。
現状、引数として渡していますが、何度も呼び出される再帰関数なので非効率的で変だと思っています。
クラススコープの下に2つのメンバ関数で共有する変数をおくスコープがあれば上手くいく感じがしています。
こういった場合、スコープを階層化するにはどうしたらいいでしょうか?
Re: スコープの階層化について
>2つのメンバ関数で共有する変数
メンバ変数ではダメなのでしょうか?
(引数渡しで解決できているのならメンバ増やすよりはそのままの方が良いと思うけど)
メンバ変数ではダメなのでしょうか?
(引数渡しで解決できているのならメンバ増やすよりはそのままの方が良いと思うけど)
Re: スコープの階層化について
usaoさん、回答ありがとうございます。
すごく一時的な変数なので、これを他のメンバ変数と一緒にするのは何か違う気がしています。usao さんが書きました:メンバ変数ではダメなのでしょうか?
Re: スコープの階層化について
みけCATさん、サンプルをありがとうございます。
こういった入れ子クラスで、内側のクラスから外側のクラスのメンバ変数にはどうやってアクセスしたらいいでしょうか。
こういった入れ子クラスで、内側のクラスから外側のクラスのメンバ変数にはどうやってアクセスしたらいいでしょうか。
Re: スコープの階層化について
スコープを階層化という表現は聞いたことがありませんが。
再帰関数そのものをローカルにしてしまえば簡単。
再帰関数そのものをローカルにしてしまえば簡単。
✜ で C ご ✜
: す + 注 :
¦ か + 文 ¦
: ? Is the は :
✜ order C++? ✜
: す + 注 :
¦ か + 文 ¦
: ? Is the は :
✜ order C++? ✜
糸冬
――――――――
制作・著作 NHK
――――――――
制作・著作 NHK
Re: スコープの階層化について
そもそもの話、質問内容の状況があまり考えられないのですが。大抵の場合はその部分を別の部品としてクラス外に吐き出せるのではないでしょうか。
Re: スコープの階層化について
>すごく一時的な変数なので、これを他のメンバ変数と一緒にするのは何か違う気がしています。
一時的な仕事をするだけのクラスか何かを作ってそいつにメンバとして持たせたらいいのでは?
(というか 何がしたいのかわからない)
一時的な仕事をするだけのクラスか何かを作ってそいつにメンバとして持たせたらいいのでは?
(というか 何がしたいのかわからない)
Re: スコープの階層化について
参照を渡すことでできました。長峰 さんが書きました:みけCATさん、サンプルをありがとうございます。
こういった入れ子クラスで、内側のクラスから外側のクラスのメンバ変数にはどうやってアクセスしたらいいでしょうか。
#include <cstdio>
class hoge {
int bar;
struct hogehoge_t {
hoge& parent;
int foo;
hogehoge_t(hoge& h): parent(h) {}
void fuga(void) {
printf("%d %d\n", foo, parent.bar);
}
void poyo(int a) {
if (a > 0) foo = a;
fuga();
}
} hogehoge;
public:
hoge(): hogehoge(*this) {}
void test(int param = 123) {
bar = param * 2;
hogehoge.poyo(param);
}
};
int main(void) {
hoge h, hh;
h.test();
hh.test(456);
h.test(-1);
return 0;
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)
Re: スコープの階層化について
nullptrさん、回答ありがとうございます。
ただ、無名関数の再帰は初めてなので不安です。関数内で名前付きの関数が宣言できればいいのですが。
具体的にはこの関数内でオブジェクトの押し出し判定を行い、押せる状況なら、連鎖的にオブジェクトを一方向にずらすというものです。
再帰関数をメンバ関数にする必要はなかったので、しっくりくる感じがします。nullptr さんが書きました:再帰関数そのものをローカルにしてしまえば簡単。
ただ、無名関数の再帰は初めてなので不安です。関数内で名前付きの関数が宣言できればいいのですが。
この関数は全てのメンバ変数を扱うものだったのでクラス内で作ったほうが収まりがいいと思ったのです。nullptr さんが書きました:そもそもの話、質問内容の状況があまり考えられないのですが。大抵の場合はその部分を別の部品としてクラス外に吐き出せるのではないでしょうか。
具体的にはこの関数内でオブジェクトの押し出し判定を行い、押せる状況なら、連鎖的にオブジェクトを一方向にずらすというものです。
Re: スコープの階層化について
発想を変えて、文法上の再帰処理を用いずに、スタックを用いた深さ優先探索のような実装ではできないものでしょうか?長峰 さんが書きました:具体的にはこの関数内でオブジェクトの押し出し判定を行い、押せる状況なら、連鎖的にオブジェクトを一方向にずらすというものです。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)
Re: スコープの階層化について
無名関数…まあ、無名関数ではありますが、関数オブジェクトとして変数に保存しているので、識別子recをつけていますから、使う分には同じことです。長峰 さんが書きました:再帰関数をメンバ関数にする必要はなかったので、しっくりくる感じがします。nullptr さんが書きました:再帰関数そのものをローカルにしてしまえば簡単。
ただ、無名関数の再帰は初めてなので不安です。関数内で名前付きの関数が宣言できればいいのですが。
みけCATさんがクラス内クラスを作っていますが、実は発想は同じものです。関数内で関数は定義できませんが、関数内でローカルクラスを定義して、関数呼び出し演算子をオーバーロードすれば(つまり関数オブジェクトを作れば)同じことができます。
#include <functional>
#include <iostream>
struct A{
int hoge(){
int foo = 0; // コイツを使いたいのかい?
struct Rec{
int& foo;
Rec( int& foo ): foo{ foo }{}
int operator()(){
return this->foo <= 10 ? this->foo++ + this->operator()() : 0;
}
} rec{ foo };
return rec();
}
};
int main(){
A a;
std::cout << a.hoge() << std::endl;
}
無名関数と怯える必要はありませんので、これを機会に関数オブジェクトを学んでみれば今回の件も幸せになれるかもしれませんね。
そもそも今回の件なら再帰ではなくてもいいような気もします。具体的にはこの関数内でオブジェクトの押し出し判定を行い、押せる状況なら、連鎖的にオブジェクトを一方向にずらすというものです。
オフトピック
今回の件、最適化の観点からするとローカルクラスで書いた方がいい?まあそもそも再帰しなければ…
✜ で C ご ✜
: す + 注 :
¦ か + 文 ¦
: ? Is the は :
✜ order C++? ✜
: す + 注 :
¦ か + 文 ¦
: ? Is the は :
✜ order C++? ✜
糸冬
――――――――
制作・著作 NHK
――――――――
制作・著作 NHK
Re: スコープの階層化について
皆さん返信ありがとうございます。
usaoさん
やっぱり自分のアプローチが適切でなかったようですね。
関数から繰り返し構文にして、調べたオブジェクトを配列に入れていくということでしょうか?
nullptrさん
納得のあまり言うことがなくなってしまいましたが、ありがとうございます。
関数オブジェクトは情報だけは知っていたのですが、変更する全てのメンバの参照を持たないといけないと思って避けていました。
考えたら、みけCATさんのコードみたいにクラスオブジェクトの参照だけでいいんですもんね。使い方が分かりました。
usaoさん
やっぱり自分のアプローチが適切でなかったようですね。
深さ優先探索について調べましたがどういった使い方をするのか検討がつきませんでした。みけCAT さんが書きました:発想を変えて、文法上の再帰処理を用いずに、スタックを用いた深さ優先探索のような実装ではできないものでしょうか?
関数から繰り返し構文にして、調べたオブジェクトを配列に入れていくということでしょうか?
nullptrさん
納得のあまり言うことがなくなってしまいましたが、ありがとうございます。
関数オブジェクトは情報だけは知っていたのですが、変更する全てのメンバの参照を持たないといけないと思って避けていました。
考えたら、みけCATさんのコードみたいにクラスオブジェクトの参照だけでいいんですもんね。使い方が分かりました。
Re: スコープの階層化について
5日も間隔を空けてしまいましたが、皆さんから見聞きした意見を元に自分の結論をまとめてお開きとさせて頂きます。
・ファイルスコープは名前空間で階層化でき、関数内ではブロックで階層化できるものの、クラススコープは継承による階層化ができるのみで、純粋なサポートはされていない。
・クラス内に作られた入れ子クラスには外側クラスのスコープが適用されるので、外側クラスのインスタンスを通してprivateメンバへアクセスできる。これによって、入れ子クラスで外側クラスの参照を保持すれば擬似的な階層化ができる。
返信をくださった皆さん、遅くなりましたがありがとうございました。
実装自体は再帰関数ではなくループ構文を利用したものに変更し、同じスコープ内の処理にしました。
・ファイルスコープは名前空間で階層化でき、関数内ではブロックで階層化できるものの、クラススコープは継承による階層化ができるのみで、純粋なサポートはされていない。
・クラス内に作られた入れ子クラスには外側クラスのスコープが適用されるので、外側クラスのインスタンスを通してprivateメンバへアクセスできる。これによって、入れ子クラスで外側クラスの参照を保持すれば擬似的な階層化ができる。
返信をくださった皆さん、遅くなりましたがありがとうございました。
実装自体は再帰関数ではなくループ構文を利用したものに変更し、同じスコープ内の処理にしました。