• ベストアンサー

関数の多重定義(同一タイプの「リファレンス」「値渡し」)

目黒@C++学習中 です。 下記のソースの実行結果が c:\c++oo\pointline\clspoint.h(27) : 値渡し   P(7,7) c:\c++oo\pointline\clspoint.h(27) : 値渡し   P(7,7) となります。 同一タイプの「リファレンス」と「値渡し」の 多重定義は可能なのでしょうか? それとも、もっと基本的な間違え? [環境]NT4 VC6.0(SP3) #include "clsPoint.h" int main() { Point oP1(2,5); Point oP2(5,2); Point oP3; Point& opP1 = oP1; Point& opP2 = oP2; oP3 = opP1 + opP2; oP3 = oP1 + oP2; cout << oP3 << endl; return 0; } #include <float.h> #include <crtdbg.h> typedef const double cdouble; class Point; typedef const Point cPoint; cdouble dNULL = DBL_MAX; class Point { private: double m_dX; double m_dY; public: Point() : m_dX(dNULL), m_dY(dNULL){}; Point(cdouble dX, cdouble dY) : m_dX(dX), m_dY(dY){}; public: Point operator + (cPoint& oP2) { _RPTF2(_CRT_WARN,"リファレンスP(%g,%g)\n",m_dX+oP2.m_dX , m_dY+oP2.m_dY); return Point(m_dX+oP2.m_dX , m_dY+oP2.m_dY); } Point operator + (cPoint oP2) { _RPTF2(_CRT_WARN,"値渡し   P(%g,%g)\n",m_dX+oP2.m_dX , m_dY+oP2.m_dY); return Point(m_dX+oP2.m_dX , m_dY+oP2.m_dY); } };

質問者が選んだベストアンサー

  • ベストアンサー
  • a-kuma
  • ベストアンサー率50% (1122/2211)
回答No.2

規約をわかってないと「?」な現象に思えますよね。 詳しくはヘルプ(C++ランゲージリファレンス→オーバーロード →引数の型の違い)を見て欲しいのですが、少し解説を。 # 私が参照できるのは VC4.2 のヘルプなので、多少表現が # 違うところがあってもご勘弁 基本的に「ある型の引数と、この型への参照は ... オーバーロードに 関しては同一とみなされます」。 ただし、「const や volatile をつけた型への参照と、基本型への 参照とは区別できます」。 typedef をつけないと、ふたつのメソッドの引数は   const Point&   const Point ですが、const Point は、メソッドの中で const として扱われる だけで、Point のコピーコンストラクタが呼ばれますから、 Point& を受け取るのと同等です。なので、   const Point&   Point& の違いであり、これは区別されるのです。 一方、operator + を呼び出す側の Point は、const ではありませんから (Point& 相当の)const Point の方で解決をします。 例えば、   const Point opP2(oP2); としてみてください。 const な opP2 を引数にする方は "リファレンス" を出力する方の メソッドが呼び出されることを確認できるはずです。 もう一度書きます。 > 同一タイプの「リファレンス」と「値渡し」の > 多重定義は可能なのでしょうか? できません。

その他の回答 (1)

  • kokucho81
  • ベストアンサー率61% (157/255)
回答No.1

基本的にあいまいな実装は、コンパイル時に、あいまいなメソッドが呼ばれる行 (個の場合、oP3=opP1+opP2)で、 警告が出ると思うんだけど… 警告が出ないというのは不思議だなー あと、同一タイプの「参照」と「値渡」では区別がつかない(意図するほうにわたせない)よね~。 参照は実際には都合上『参照型』といっているだけで、参照型という型を持っているわけではないので、区別が・・・・ oP3 = (Point&)oP1 + (Point&)oP2; で渡せるかもね(あまりしないというか定義してもこれでは使われない) Point& ooP1は常に oP1と置き換えてよまんといかんです。 あと、似たような議題があがるのは、 変換コンストラクタと、変換演算子とか・・・

関連するQ&A

  • 誤った関数に関する値渡しについて

    こんにちは、まずはソースを記述します。 #include<iostream> using namespace std; //誤ったswap関数の宣言 void swap(int x, int y); int main() { int num1 = 5; int num2 = 10; cout << "変数num1の値は" << num1 << "です。\n"; cout << "変数num2の値は" << num2 << "です。\n"; cout << "変数num1とnum2の値を交換します。\n"; swap(num1, num2); cout << "変数num1の値は" << num1 << "です。\n"; cout << "変数num2の値は" << num2 << "です。\n"; return 0; } //誤ったswap関数の定義 void swap(int x, int y) { int tmp; tmp = x; x = y; y = tmp; } >>関数内で仮引数xとyの値を交換する処理を行っていても、これは変数num1とnum2の値を「コピー」した5と10を交換しているにすぎません。 swap関数内で値を交換しても、呼び出し元の変数であるnum1とnum2に影響を与えることができません。 ・・の文章の中から質問ですが値渡しとはどういうことでしょうか? 参照渡しとはどう違うのでしょうか? ご教示お願いします。

  • C言語の、戻り値/値渡し/アドレス渡しのついて

    【実装したコードに、戻り値/値渡し/アドレス渡しを用いたサブの関数を作成せよ。】 上記の課題に取り組んでいるのですが、何となく概念は分かったのですが、ソースコードに反映させようとすると詰まってしまって… どなたか教えて頂けないでしょうか? 『ソースコード』 #include <stdio.h> #include <time.h> #include <string.h> #include <stdlib.h> #define CALC (3) #define FROM_YEAR (1900) #define MAX_LINE (1000) int cmp_u(const void* a, const void* d) { return strcmp((char*)a, (char*)d); } int cmp_d(const void* a, const void* d) { return strcmp((char*)d, (char*)a); } int main() { int num1, num2; char op; float answer; int r,i; FILE* fp; char e[11]; char sin[1000][1000]; char ad[8]; fp = fopen("log.txt", "a+"); if (fp == NULL) { printf("ファイルオープン失敗\n"); return -1; } while (1) { r = scanf("%d%c%d", &num1,&op, &num2); if (r != CALC) { puts("input error"); return 1; } if (op == '+') { answer = num1 + num2; } else if (op == '-') { answer = num1 - num2; } else if (op == '*') { answer = num1 * num2; } else if (op == '/') { answer = (float)num1 / num2; } time_t t = time(NULL); struct tm* tm = localtime(&t); printf("%d/%02d/%02d ", tm->tm_year + FROM_YEAR, tm->tm_mon + 1, tm->tm_mday); printf("%02d:%02d:%02d ", tm->tm_hour, tm->tm_min, tm->tm_sec); printf("%d%c%d,%f\n", num1, op, num2, answer); fprintf(fp, "%d/%02d/%02d ", tm->tm_year + FROM_YEAR, tm->tm_mon + 1, tm->tm_mday); fprintf(fp, "%02d:%02d:%02d ", tm->tm_hour, tm->tm_min, tm->tm_sec); fprintf(fp, "%d%c%d,%f\n", num1, op, num2, answer); printf("計算を続けますか?"); scanf("%s", e); if (strcmp(e, "no") == 0) { break ; } } fclose(fp); fp = fopen("log.txt", "r"); int cnt = 0; for (i = 0;i < MAX_LINE;i = i + 1) { if (fgets(sin[i], sizeof(sin[0]), fp)) ++cnt; else break; } fclose(fp); printf("ASC or DESC: "); scanf("%s", ad); if (strcmp(ad, "ASC") == 0) { qsort(sin, cnt, sizeof(sin[0]), cmp_u); } else { qsort(sin, cnt, sizeof(sin[0]), cmp_d); } for (i = 0;i < cnt;i = i + 1) { printf("%s", sin[i]); } return 0; }

  • +演算子オーバーロード

    こんにちは。お世話になっております。 // +演算子オーバーロード CPoint CPoint::operator+(CPoint& obj) //~(1) { CPoint tmp; tmp.m_x = m_x + obj.m_x; tmp.m_y = m_y + obj.m_y; return tmp; } int main() { CPoint point1( 100, 150 ); CPoint point2( 200, 50 ); std::cout << "x:" << point1.getx() << "y:" << point1.gety() << std::endl; point1 = point1 + point2; // オーバーロードされた+演算子が呼び出される std::cout << "x:" << point1.getx() << "y:" << point1.gety() << std::endl; point1 += point2; // オーバーロードされた+=演算子が呼び出される std::cout << "x:" << point1.getx() << "y:" << point1.gety() << std::endl; return 0; } 某サイトで上のようなサンプルプログラムがあるのですが これはc++で書かれた「+演算子オーバーロード」の定義で、動作としては 「point1 = point1.operator+( point2 ); // point1 = point1 + point2; と同じ」というような動作です。 それで疑問が出てきたのですが、イコールの右側で足す数が↓のような3つの場合、ans = a + b + c;です。 これだと(1)のところの引数を2つをとる関数を別に作らないとだめでしょうか?それとも、ans = ((a + b) + c);というふうに優先順位で自動的に計算してくれる+演算子オーバーロードのプログラムを教えてくれませんか?↑式のカッコは便宜上付けただけで、出来ればans = a + b + c;だけで計算出来るプログラムを教えてください。

  • typedef定義型を使った関数について

    はじめて質問させていただきます。 Visual C++ 2008 Express Editionを使ってC言語のソースコードを記述しています。 (OSはWindows XPを使用しています。) ビルドを行った際に以下のエラーが発生していて、先に進めません。 色々と調べてみたのですが、解決方法がわからず質問させていただいた次第です。 解決方法についてご存知の方がいらっしゃいましたら、回答いただけると嬉しいです。 ■エラー内容 ------ ビルド開始: プロジェクト: Sample, 構成: Debug Win32 ------ コンパイルしています... Sample.c d:\sample\sample\Sample.c(4) : error C2061: 構文エラー : 識別子 'GetInfo' d:\sample\sample\Sample.c(4) : error C2059: 構文エラー : ';' d:\sample\sample\Sample.c(4) : error C2059: 構文エラー : ')' ビルドログは "file://d:\Sample\Sample\Debug\BuildLog.htm" に保存されました。 Sample - エラー 3、警告 0 ========== ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ ========== ■Sample.c #include "stdafx.h" Info GetInfo(){ return 0; } int main(){ return 0; } ■stdafx.h #pragma once #include "def.h" #include <stdio.h> #include <tchar.h> Info GetInfo(); ■def.h typedef struct Info{ int a; int b; int c; } Info;

  • char *の書き換え

    #include <iostream.h> int main(){  char *p = "abcdef";  p[3] = 'g';  cout << p[3];  return 0; } C++です。 p[3] = 'g'; は、やってはいけないことですか?

  • 標準ライブラリのcos関数の値がおかしいです。

    標準ライブラリのcos関数の値がおかしいです。 環境は OS:WindowsXP 言語:C++ 開発環境:Visual C++ ExpressiEdition です。 以下がサンプルコードです。 #include<iostream> #include<stdio.h> #include<math.h> int main(){ double y=cos(90.0 * 3.14159265358979323846264338327950288 / 180.0); printf("%lf\n",y); std::cout<<y<<std::endl; printf("%d\n",y*10); std::cout<<y*10<<std::endl; getchar(); return 0; } 上記のコードを実行すると、 0.000000 6.12323e-017 -1076268279 6.12323e-016 と出力されます。 本来なら、cos90の値は0ですから全て「0」と表示されると思うのですが・・・ 原因が分かる方がいらっしゃいましたら、教えていただけると助かります。

  • 続ポインタによる関数への配列渡し

    連続での質問すみません。 林晴比古さんの「新C言語入門」で勉強している初心者です。 ポインタを勉強中で、色々な例文をポインタで書けるかどうか 試しております。 上書P199に「安全な数値入力を行うプログラム」が出ています。 これは入力時問題点を抱えるscanfに入力させるのでなくchar型に入力させ、 それをint型に変換して出力するという内容で、案内メッセージも関数内で表示することになっています。 以下そのプログラムを引用します。 #include <stdio.h> #include <stdlib.h> int getint(char msg[]); int main(void) { int n; n = getint("数値を入力してください:"); printf("入力した数値=%d\n",n); return 0; } int getint(char msg[]) { char ss[80]; printf("%s",msg); gets(ss); return atoi(ss); } (以上林晴比古氏「新C言語入門」P199より引用) これをポインタによって書き換えようとしているのですがうまくいきません。 「本引数として主文でint型のnを設定し、それを関数側のchar型のssをポインタにして 仮引数として受け取れば、最後にreturnで返さなくても、参照できるのでないか」 と思い色々試してみましたがうまくいきません。 どうもコンパイルのエラーを確認すると型が違うので駄目なようです。 なるほどそれはそうでした… それ以外の方法も色々試してみましたが、結局うまくいきませんでした。 どのようにすればポインタでは上の文章を表現できるのでしょうか。 (あるいは表現出来ないのでしょうか) お分かりの方、よろしくお願いします。

  • このプログラムについて。

    #include <stdio.h> #include <stdlib.h> #include <math.h> #include <time.h> #include <string.h> #define NVALUE 30 #define MAXSIZE NVALUE struct City{ float x; float y; }; struct Country{ struct City cities[MAXSIZE]; int size; }; struct Itine{ float quality; int route[MAXSIZE]; int noc; }; float plength(struct Itine *tour,struct Country *pcountry) { int i,j; double dy; double dx; float length=0.0; for(i=0;i<tour->noc;i++){ j=i+1; if(j==tour->noc) j=0; struct City &c1=pcountry->cities[tour->route[i]-1]; struct City &c2=pcountry->cities[tour->route[j]-1]; double dx = c1.x-c2.x; double dy = c1.y-c2.y; length+=(float)sqrt(dx*dx+dy*dy); } return length; } なんか間違っていますか? エラーメッセージは、この部分 struct City &c1=pcountry->cities[tour->route[i]-1]; struct City &c2=pcountry->cities[tour->route[j]-1]; double dx = c1.x-c2.x; double dy = c1.y-c2.y; が、 ';'が'型'の前にありません と出ています。Visual Express 2005です。

  • dy/dx (y+1)を積分して(y+1)^2?

    次の微分方程式の一般解を求めよ。 (1+y) (d^2y)/(dx^2) + (dy/dx)^2 = 0 dy/dx = p とおくと、      (1+y)p (dp)/(dy) + p^2 = 0 となり、      (i) (1+y) (dp)/(dy) + p = 0      (ii) p = 0 の2通りが考えられる。 (i)の場合      1/p (dp)/(dy) + 1/(1+y) = 0 の両辺をyで積分して      log |p(y+1)| = C_1 つまり、      dy/dx (y+1) = C_1 両辺をxで積分して、      (y+1)^2 = C_1x + C_2     ←? という解を得る。 ・・・と本に書いてあります。しかし、 「両辺をxで積分して」の計算は間違ってないですか? 自分が計算すると、      dy/dx (y+1) = C_1      ∫ (y+1) dy/dx dx = C_1∫dx      ∫ (y+1) dy = C_1∫dx      ∫y dy + ∫1 dy = C_1∫dx      y^2/2 + y = C_1x + C_2 になります。 積分して(y+1)^2になるなら、元々は2(y+1)じゃないといけないですよね、きっと。 ということで、どなたか検算をお願いします。

  • ポインタによる関数への配列渡し

    林晴比古さんの「新C言語入門」でC言語を勉強している初心者です。 現在ポインタの勉強をしています。色々教科書の文例等をポインタで書くとどうなるか試しております。 上書P200練習問題2に「配列の最大値を返す(その際配列の長さを渡す)」プログラムがあり、それをポインタで渡すプログラムに直してみました。 仮引数に「maxdata」を設定し、そのアドレスを関数側に渡し、関数側ではポインタとして受け取る(そうすれば関数側からはreturnで値を返す必要がない)、と考え、下記のように書いてみました。 #include <stdio.h> void max_of_array(int n[], int len, int *ans); int main(void) { int dt[6] = {50,20,80,30,10,40}; int maxdata; max_of_array(dt,6,&maxdata); printf("最大値=%d\n", maxdata); return 0; } void max_of_array(int n[], int len, int *ans) { int i; ans = &n[0]; for (i=1; i<len; i++){ if (*ans < n[i]) *ans = n[i]; } } しかしコンパイルすると、何故か「最大値=1」となってしまいます。(正しくは80です) 他にも色々試してみましたがうまくいかず、かなり考えてみたのですがどうしても分かりません。お分かりの方、どうすれば正しくなるのが教えてください、よろしくお願いします。