• ベストアンサー

代入の方法(C++)

bobの回答

  • bob
  • ベストアンサー率50% (52/103)
回答No.1

このケースでは2通り考えられます。 (1) void T :: f( const T& v, ...) { ~~~; } もしくは T& T :: f( const T& v, ...) { ~~~; return *this; } を定義して a.f(v, ...); でaを書き換える (2) T& T :: f(...) { ~~~; return *this; } を定義して a = v.f(...); でaを書き換える どちらを選ぶかはオブジェクト指向ですから、T::fがどう言う意味を持つかによって選ぶのがいいと思います。(1)だと他のオブジェクトvとその他の引き数を入力にしてオブジェクト自身を書き換えるメソッドになりますし、(2)だと本質はその他の引き数でオブジェクト自身を書き換えることで、その結果をたまたま他のオブジェクトaにコピーしているという解釈になります。 a=v.f(...); 以外の形でメソッドfを使うことが無いようなら(1)の方が明示的でいいかも知れません。vを書き換えたくない場合も(1)を使うことになります。 返り値に&をつけると、返り値のオブジェクトが左辺値に使えるようになります。寿命は参照するオブジェクトの寿命と同じで、それ以降は値の保証はないです。上の2例では*thisを返しているのでメソッドを呼び出したオブジェクトの寿命と等しくなります。 返り値に&がつかない場合、特に(2)では一時オブジェクトに返り値がコピーされたのをまたaにコピーすると言う形になると思われるので2度手間の印象があります。

motsuan
質問者

お礼

どうもありがとうございます。 (2)の解釈なのですが、やりたいこととしては b = a.f(...); のような場合と a = a.f(...); の場合の2つがあり、 単なるf(...) とaにaを変更するメソッドf(a,...) を用意するようなことは 面倒であるとともに、メンテナンス上よくないような気がしています。 (実際問題としてはf(a,...) の中で  a = a.f(...)を実行すればいいのでしょうけれど) この場合、新しいインスタンスvに対して初期化または代入により  v=a; という状態を実現し、  a=v.(...); というのもちょっと変なような気もするんです。 どうもこのあたりのもやもやがC++の分からないところなのかなぁと思っています。 どうもありがとうございました。

関連するQ&A

  • C言語(引数)

    はじめまして。 C言語を習い始めたものです。 関数を定義するとき、よく耳にする、仮引数や実引数があると思います。 仮引数は関数の定義内で値をうけとる変数のことであり 実引数は関数を呼び出す際に渡す値を実引数というらしいのですが どこからどこまでを仮引数と呼ぶのかわかりません。 例えば、 fの関数の定義内で ↓があるとします。 (関数にする意味はないのですが、確認のためあしからず・・・) double f(double x) {     x=5;     return(x); } この場合、仮引数とよばれるものは double f(double x)の xが仮引数であって x=5;のxは仮引数と呼ばないのでしょうか?? もしそうならば void f(double x) { printf("%f",x); } のprintf("%f",x);内のxは仮引数とよぶのでしょうか? 質問の内容が意味不明かもしれませんが よろしくお願いします。

  • 関数に値の代入 [C言語]

    C言語初心者です。関数とポインタについて勉強していたのですが、ふと関数の型を知りたくなってVC++で型を調べてみたんです。そしたら、void型で引数のない関数の型は void (__cdecl*)() となっていました。voidと__cdeclはわかります。 そしてこれ型に*が入ってるじゃないですか。ということは関数はポインタということになると思います。なので私はもしかしたら値の代入ができるのではないか、と思ったのです。早速、 f1=f2;(f1とf2は型と内容の同じ関数) や、 (*f1)=(*f2); としてポインタの中身や参照先の関数の実態の値を処理中に書き換えてみようとしました。ですが、多分そうなるとは思ったのですが、コンパイルエラーが出ました。 《エラーの内容》 error C2106:'=':左のオペランドが、左辺値になっていません。 warning C4550:式は引数リストのない関数として評価します。 関数を書き換えようとすること自体馬鹿げていることは重々承知です。でも、微かにいけそうな気がするんですよ。代入させたくないなら関数の型は一律constにすると思うし(実際関数をconstをつけて宣言してもOKだった、(プロトタイプ有り無しでも))、関数への代入は問答無用で駄目なのならばそういうエラーメッセージを出すと思うんです。 関数の書き換えは100%無理でしょうか?それとも関数を書き換える方法があるでしょうか?回答よろしくお願いします。

  • 警告「代入される前に使われている」を出す方法

    bccで以下のコードをコンパイルすると。 「'i' は、おそらく値が代入される前に使われている」 と警告が出ますが、 「'h' は、おそらく値が代入される前に使われている」 とは警告を出してくれません。 警告を出す方法ってないでしょうか? Hogeメンバに bool 型の初期化フラグでも実装しようかな・・・。 #include <iostream> class Hoge { public: Hoge(){ } Hoge( int i ){ t = i; } operator int(){ return t; } int t; }; int main() { int i; Hoge h; std::cout << i << std::endl; std::cout << h << std::endl; return 0; }

  • c言語の関数定義について

    次の関数定義を考える. int f(int x) {if (x > 0) {return x * f(x-1);} else {return 1;} } この関数f と働き(すなわち,引数と戻り値の関係)が同じで再帰呼出(recursive call) を使わない関数g をC で定義せよ.ただし,オーバーフロー(overflow) については考慮しなくてよい. ”この関数f と働き(すなわち,引数と戻り値の関係)が同じで再帰呼出(recursive call) を使わない関数g をC で定義せよ”って理解できません、どのように定義したいいか、ご教授お願いします。

  • 【C++】関数ポインタの使い方

    関数ポインタの使い方で悩んでいます。 下記の (1)のようにグローバルメソッドとして定義したメソッドを関数ポインタに代入することは出来るのですが、 (2)のようにクラスのメンバメソッドとして定義したメソッドは関数ポインタに代入することは出来ませんでした。 Error:バインドされた関数へのポインターは関数の呼び出しにのみ使用できます。 というエラーが発生します。 関数ポインタに外部参照でメソッドを代入することは出来ないのでしょうか? -----(1)------------------------------------------------------------------ #include "stdafx.h" #include <iostream> using namespace std; int f(int a, int b){ return a * b; } int _tmain(int argc, _TCHAR* argv[]) { typedef int (* FUNC_POINTER)(int, int); FUNC_POINTER fp; fp = f; cout << fp(1,2) <<endl; getchar(); return 0; } ------------------------------------------------------------------------- -----(2)------------------------------------------------------------------ #include "stdafx.h" #include <iostream> using namespace std; class MPointerList{ public: int f(int a, int b){ return a * b; } }; int _tmain(int argc, _TCHAR* argv[]) { typedef int (* FUNC_POINTER)(int, int); FUNC_POINTER fp; //fp = f; MPointerList mP; fp = mP.f; cout << fp(1,2) <<endl; getchar(); return 0; } -------------------------------------------------------------------------

  • C++ template operator T()

    ソースを見ていて分からないところがあったので教えて下さい。 なんと説明すればいいのか分からないので下に要約したソースを書きます。 template <typename T> class Hoge { T a_; public: Hoge(T a = 0) : a_(a) {} operator T() const { // ココが分からない return a_; } }; 最初は、関数オブジェクトかと思ったのですがそうではないですよね? operator()(引数) ですよね? 次は、Tのコンストラクタかと思ったのですが、class Hoge の中に書くのも変な気がしました。

  • 引数について質問

    私プログラミング初心者ですので、できるだけ優しい解説をしていただければ幸いです! 引数について、以下のような解説がありました。 「引数には仮引数と実引数の2種類が存在する。仮引数は、関数を定義する際に変数で指定する引数である。また、実引数は、プログラムの実行時に関数に引き渡される値となる引数である。つまり、関数の実行時には、実引数の値が仮引数に代入されることになる。」 質問:1「関数を定義する際に変数で指定する引数である。」という記述の中で「関数を定義」とありますが、実際のソースコードにおいて何に対応するかわかりません。簡潔なソースコードを交えて解説していただければ幸いです。 質問2:「関数を定義」に限らず、プログラミングにおいて「定義」という言葉をよく見ますが、これは本質的にどういう意味をもっているのでしょうか?具体的なソースコースコードを交えて解説してくださると幸いです。 もしかして、その定義とは例えば「public static void main(String arg[]){」のような「メソッド宣言」のことですか? 質問3:「関数の実行時には、実引数の値が仮引数に代入されることになる。」と書いてありますが、 これはどういうことですか、僕が実際にソースコードで記述してみるので、その考えが正しいか判定してください package 第4章; public class A { public static void main(String arg[]){ double x; x=Math.sqrt(2.0); System.out.println("2.0の平方根は"+x); } } 僕の考え:String arg[]が仮引数で、実引数2.0がString arg[]に代入されるってことでしょうか? 「定義」といえば、上記のソースコードでは、public static void main(String arg[]){ 以外見当たらないので、、 僕の考え2:Mathクラスは、標準クラス(javaが最初から備えているクラス)だから、プログラマが「関数を定義」しなくても予め関数が定義されているから、関数を定義する必要がない、ということでしょうか?

    • ベストアンサー
    • Java
  • C++で継承元のクラスの代入演算子を呼び出す方法

    C++であるクラス継承したクラスの代入演算子で 継承元のクラスの代入演算子を呼び出す方法がわかりません。 こんな感じのソースです。 class T { T& operator=(const T &t) { } } class U :: T{ U& operator=(const U &u) { // ここでT.operator=()の代入演算を実行したい } } ((T)(*this)).operator=((T)(u))のようにキャストすればいけるかと思ったんですが、 コンパイルエラーでした。 よろしくお願いします。 また、これはプログラム上好ましくない手法でしたら、 別な実現方法をお教えください。

  • C言語 exitで終了した関数の戻り値

    引数が負の整数であればエラーを表示し終了、0以上の整数であればそのまま戻り値とする関数 int example(int a) { if( a < 0 ) { printf("Error!\n");   exit(1); } return(a); } があったとします。 ここでたとえば  int s1,s2; に対して、 s1 = example(3); とすれば、 s1 = 3 となりますが、 s2 = example(-5); とすれば、 s2 には何が代入されているのでしょうか? 例に書いた関数はしょーもないものですが、 もう少し難しい関数を使って変数に値を入れて、その値で後でfor文などを使って仕分けていくようにしたいのですが、エラー時に代入されるものがわからなくて困っています。 エラー時のみに目印となる値、たとえば -1 などを戻り値とすることはできません。 おねがいします。

  • 合成積の式にフーリエ変換の関数を代入可能ですか?

    (f*g)(t) = ∫[-∞,∞] f(s) g(t-s) ds のf(s)とg(t-s)の部分にフーリエ変換の関数F(s)とG(k-s)を代入できますか? 定義を二つ書きます: ・フーリエ変換の式 F(k) = ∫[∞,-∞] f(t) exp^(-ikt) dt (式5.26) 関数F(k)は非周期関数f(t)のフーリエ変換と呼ばれ、(式5.26)はフーリエ変換を計算する式である。 ・合成積 区分的に滑らかで絶対可積分である2つの関数f(t), g(t)が与えられたとき、f(t)とg(t)の合成積(または、たたみこみ)を (f*g)(t) = ∫[∞,-∞] f(s) g(t-s) ds (式6.28) によって定義する。この式の左辺では、f*gが1つの関数の名前であることをはっきり示すために括弧で括ってあり、合成積はtの関数なので(t)と書いてある。 ・・・上記二つの式を踏まえて、 (F*G)(t) = ∫[∞,-∞] F(s) G(k-s) ds (式6.28)' と代入できますか?