プログラムの途中で次のエラーが出ました。

error C2667: '>>' : 2個のオーバーロード関数があいまいで最適な変換ができません。
error C2593: 'operator >>' があいまいです。

調べましたらVisual C++自体のバグらしいのです。

http://support.microsoft.com/support/kb/articles …
http://support.microsoft.com/support/kb/articles …

僕のVisual C++はVersion 5.0です。
学校のはVersion 6.0ですのでこのバグは出ません。

このバグを回避する方法は無いのでしょうか?
Version 5.0を使用されている方は結構いらっしゃるのではないかと
思うのですが、皆さんはどうされているのでしょうか?

一応、関係ありそうなところだけ抜粋しました。

■main.cpp
shareholder total[size];// 全員の名前が入る予定のtotal[]を
// class "shareholder"で定義

total[s].getData(input);// 関数getData()を呼ぶ
// inputはifstreamで定義されている

■shareholder.h
class shareholder
{
public:

shareholder();
virtual ~shareholder();

void getData(ifstream&);

private:

string firstName;
string lastName;
};

■shareholder.cpp
void shareholder::getData(ifstream& inputFunction)
{
inputFunction >> firstName >> lastName;// ここでエラーが発生
}

このQ&Aに関連する最新のQ&A

A 回答 (2件)

> 回避方法って、要するに>>を使わなきゃいいんですよ。



その通り。

…で終るのも殺生なんで、代替案を。

1.getline(inputFunction, firstName)

  でfirstNameに一行読み込み、

  lastName = firstName.substr(firstName.rfind(' ') + 1)
  firstName = firstName.substr(0, firstName.find(' '))

  とかやって分ける。  
  でもなぁ。これもおなじバグが影響しそう。
  特に、Q240/8/69.ASP のバグがほんとに影響してるなら、
  多分、出ますね。
  std/bastring.hの中で、operator>>(ifstream, string)と同じ
  ように、バリバリtemplateを使って宣言されてるんで。

2.char str[MAX_BYTES_PER_LINE+1];
  inputFunction.getline(str, MAX_BYTES_PER_LINE);

  でstrに一行読み込み、

  char fn[MAX_BYTES_PER_LINE+1], ln[MAX_BYTES_PER_LINE+1];
  sscanf(str, "%s %s", fn, ln);

  で分ける。分け方は、strで初期化したstringオブジェクトをつくって、
  1.と同様の方法で分けても良いです。Cの関数を使いたくないなら。

3.最初からストリームをCの標準入出力関数fopen(...)で開いて、
  fscanfで読み込む。

  *scanf(...)は、ifstream::operator>>(...)と同じくスペースを区切り記号
  とみなすので、getline(...)のように分ける手間は省けます。

他にも色々あると思います。とにかく、やばいのは使わないことです。

私の周りにも、VC++経験者で(ちなみに私はGNU C++です)
templateを極端に嫌う人がいます。(ちなみに私はこれでもかって位
使います。)
    • good
    • 0
この回答へのお礼

>>を使わない、というのはそういう意味だったのですね。

1.getline(inputFunction, firstName)が見事成功しました。
firstNameの名前をfullNameに変えてクラスのメンバーに入れましたが
その他はFookyさんの回答をコピーしただけです。

2.と3.はまだ試してません。今度やってみます
(というか、もう動いたのでいいのですが)。

オーバーロードというのが何なのかさえ判らないというのもあるのですが、
あいまいです、ってぶっきらぼうに言われても困りますよね。
だからバグなんでしょうけど。
そういうエラーメッセージの方がよっぽどあいまいだと思うのですが。

とにかく、この問題が発生する度に毎回これを使えばいいのですね。
本当に助かりました。ありがとうございました。

お礼日時:2001/06/29 11:45

回避方法って、要するに>>を使わなきゃいいんですよ。

この回答への補足

確かに的を得た回答でしたが、Fookyさんのように詳しく書いて戴きたかったです。そもそも「>>を使わなきゃいい」と聞いて「ああ、なるほど」というレベルであれば質問はしていないと思います。仕事としてではなく、自発的に回答して下さっているのですから、1から10まですべて教えて欲しいとは言いませんが、もう少し説明して下さっても罰は当たらないと思います。その分、質問者は回答者に感謝の言葉を返しているのです。今回は残念ですがKOH_daさんに対して感謝の言葉を述べることはできません。しかし、理由は理解していただけると思っています。次回からはよろしくお願いします。

補足日時:2001/06/29 11:49
    • good
    • 0

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Qオーバーロードはオブジェクト指向プログラミングの枠組みで語られるべきか

一部の書籍やサイトでは、オーバーロードがオブジェクト指向プログラミングの特徴であるかのような記述が見受けられるのですが、私はそれに疑問を感じます。
オーバーライドはクラス・継承に関わるためOOP特有のものであると思うのですが、オーバーロードはクラスとは全く切り離して考えられるからです。
確かにオーバーロードはクラスを作るときに有用な技術ではありますが、例えばC言語のような非オブジェクト指向言語でオーバーロードが使えたとしても、それなりに機能するはずです。
ひょっとしたら
「オーバーロードもオーバーライドもポリモーフィズムだろう」

「ポリモーフィズムといえばオブジェクト指向」
のような話の展開でしょうか(いや、さすがに無理があるか…)。

皆様はどうお考えでしょうか。
ご意見お聞かせ下さい。

Aベストアンサー

おっしゃるとおり、オーバーロード・オーバーライドは非オブジェクト指向言語にもありました。
オーバーロード・オーバーライドは、「異なった関数(メソッド)を同じ名前で呼び出せる・・・引数の型・数によって実際に呼び出される関数が選ばれる」というトーンですが、ポリモーフィズムは、「1つの関数(メソッド)が引き渡される引数の型・数に応じて動作を変える」というトーンだと思います。

Qc 文字列の終わりを示すコードは 0x00 それとも '?0' , '/0' ?

cの本を参考にプログラムをかじっているのですが、
本には '?0' と書いてあり、それで出力してみるとうまくいかず
いろいろインターネットで調べたのですが、
0x00 だとうまくいきました。
良くわからないのですが、なぜでしょう?

スミマセンおねがいします。

Aベストアンサー

文字列の最後には'\0'(NULL)が必要になります。
0x00で上手くいったのは、
NULLも「整数値の0」だからです。

Qオーバーロード、オーバーライド、コンストラクタについて

オブジェクト指向と言われているオーバーロード、オーバーライドの違いを詳しく教えてください。また、コンストラクタがオーバーライドするってことはあるのでしょうか??
一応、スーパークラス・サブクラスという言葉は知っています。

Aベストアンサー

オーバーロードについては他の方の説明で十分だと思います。

例えばこんな感じですね:
class A {
  public void method() {}
  public void method(int x) {}
  public void method(double x) {}
  public void method(Object x) {}
}

オーバーライドについてですが、これは分かりやすく言うとスーパークラスやスーパーインタフェースのメソッドを継承する代わりに上書きすることです。
(継承についてはお分かりですよね?)

例:
class P {
  public void method() {
    // ここで何かをする
  }
}
class Q extends P {
  public void method() {
    // ここで別な何かをする
  }
}
class R extends P {
}

PのサブクラスであるQでは、methodというメソッドを上書きしているわけです。これが「オーバーライド」です。
RもPのサブクラスですが、methodというメソッドは上書きしていません。この場合、methodというメソッドはPからRに「継承」されるのです。

なお、上書きされるメソッドが抽象(abstract)メソッドの場合、「オーバーライド」とは言わずに「実装」といいます。したがって、King-of-Walkingさんの回答に出てきたHttpServletの例は厳密には正しくありません。(もっとも、これはJavaにおける単純な言葉の使い分けの問題ですが)

なお、Javaではコンストラクタがオーバーライドされることはありえません。(オーバーロードは可能です)
コンストラクタはクラスのメンバーではないので、継承されることはありません。したがって、上書きすることもできないのです。(コンストラクタはクラスごとに独立しているということです)

ただし、Java以外のオブジェクト指向言語ではオーバーライドや継承などといった用語の意味が多少異なることがあるので注意してください。
上に書いた説明も、Java以外の言語では正しくない可能性があります。
(toginoさんが関数という言葉を用いていますが、Javaには関数と呼ばれるものは存在しません。おそらく、メソッドのことを誤って関数と呼んでいるのでしょう。言語によって用語の意味が異なるというのはこういうことです)

オーバーロードについては他の方の説明で十分だと思います。

例えばこんな感じですね:
class A {
  public void method() {}
  public void method(int x) {}
  public void method(double x) {}
  public void method(Object x) {}
}

オーバーライドについてですが、これは分かりやすく言うとスーパークラスやスーパーインタフェースのメソッドを継承する代わりに上書きすることです。
(継承についてはお分かりですよね?)

例:
class P {
  public void method() {
    // ここ...続きを読む

Qvoid (*signal(int signum, void (*handler)(int)))(int);

の解釈を教えてください
最後の「(int)」については詳しくお願いします

Aベストアンサー

signalが

(1)1つ目の引数の型:int
(2)2つ目の引数の型:引数がintで戻り値がvoidである関数へのポインタ
(3)戻り値の型:引数がintで戻り値がvoidである関数へのポインタ(2と同じ)

を満たす関数である事を宣言しています。最後の(int)はsignalの戻り値の
関数ポインタがint型の引数を持つ事を示しています。

「引数がintで戻り値がvoidである関数へのポインタ」の型をHANDLERと表すと

HANDLER signal(int signum, HANDLER handler);

となります。

Qメソッドのオーバーロードとオーバーライドのシグニチャはどうして違うの?

オーバーロードのほうはメソッド名+引数の数+引数のデータ型ですが、オーバーライドのほうはそれに加えて戻り値の型も加わります。
どうして同じではいけないのでしょうか?

Aベストアンサー

まず、シグネチャという言葉の使い方が間違っています。Javaにおいて「メソッドのシグネチャ」とは「メソッドの名前と引数の数と引数の型」という意味です。したがって「オーバーライドのシグネチャ」とか「オーバーロードのシグネチャ」などという表現は意味を成しません。「オーバーライド時に共通させるもの」などと表現してください。

> 一応どのクラスが何をするのかということを把握して作成しているものには何も不都合が感じないと思いますが。ここでは大規模開発のことで他人の作成した……

その程度ではオブジェクトの「多態性」は実現できません。
サブクラスがスーパークラスと互換性のあるインターフェースを備えていることのは多態性の必要条件です。そうでなければサブクラスにスーパークラスの振りをさせる意味がありません。(スーパークラスとサブクラスという親子関係を作る意味がないといっても良い)
二つのクラスに親子関係を作り、両者に互換性(というか共通性)を持たせようとするのであれば、オーバーライド関係にあるメソッドの振る舞い(=何という名前で何型の引数を受け取り何型の値を返すのか)が同じになるのは当然ではありませんか?

Javaは型の扱いが厳密であることも忘れないでください。JavaScriptのような、型を演算時にしかチェックしない放任主義の言語ではないのです。

参考URL:http://msugai.fc2web.com/java/polymorphism.html

まず、シグネチャという言葉の使い方が間違っています。Javaにおいて「メソッドのシグネチャ」とは「メソッドの名前と引数の数と引数の型」という意味です。したがって「オーバーライドのシグネチャ」とか「オーバーロードのシグネチャ」などという表現は意味を成しません。「オーバーライド時に共通させるもの」などと表現してください。

> 一応どのクラスが何をするのかということを把握して作成しているものには何も不都合が感じないと思いますが。ここでは大規模開発のことで他人の作成した……

その程度...続きを読む

Qname[3] = seq + '0';の意味

オライリーC実践プログラミングのP203、例13-11の例で質問です。
このプログラムでは一時的なファイル名を返す関数、tmp_nameがあるのですが
このプログラム中の以下の行がよく分かりません。
name[3] = sequence + '0';

直感的にsequenceだけでよさそうな気がするのですが以下のように書き直すと
出力結果にsequenceの数字がでずただ"tmp"と出力されるだけでした。
name[3] = sequence;


char型にint型を使うための手段なのでしょうか?
下記にプログラム全体を載せておきます。よろしくお願いします。

#include <stdio.h>
#include <string.h>

char *tmp_name(void)
{
static char name[30];
static int sequence = 0;

++sequence;

strcpy(name, "tmp");

name[3] = sequence + '0';
name[4] = '\0';

return (name);

}

int main()
{
char *tmp_name(void);

printf("%s\n", tmp_name());

return (0);
}

オライリーC実践プログラミングのP203、例13-11の例で質問です。
このプログラムでは一時的なファイル名を返す関数、tmp_nameがあるのですが
このプログラム中の以下の行がよく分かりません。
name[3] = sequence + '0';

直感的にsequenceだけでよさそうな気がするのですが以下のように書き直すと
出力結果にsequenceの数字がでずただ"tmp"と出力されるだけでした。
name[3] = sequence;


char型にint型を使うための手段なのでしょうか?
下記にプログラム全体を載せておきます。よろしくお願いします。

#incl...続きを読む

Aベストアンサー

これは、0から9までの数値をそれに対応する文字に変換するお手軽かつ問題のある手法です。

ご存知かもしれませんが、コンピューターでは文字は内部的には対応する数値で表されています。
ですから、C/C++ではchar形の中にあるのは文字ではなくその文字に対応する数値です。
したがって、
sequence + '0'
は0という文字を表す数値にsequenceを足した値になります。文字と数値の対応はたいてい0という文字の次に1, 2, ..., 9と続くようになっていますので、結果、sequenceが0なら0という文字を表す数値、sequenceが1なら1という文字を表す数値、…という値になります。
参考キーワードとして「ASCIIコード」を調べるといいでしょう。

数値から文字への変換がたった1回の足し算で出来る、とってもお手軽な方法ですよね?

でも、以下のように問題があるのであまり使わないほうがいい方法です。

・0から9までしか使えない
上で書いたとおり、この方法でsequenceが0なら0という文字に、1なら1という文字に変換できます。……では、sequenceが-1だったら?10だったら?

・そもそも前提に疑問が残る
文字と数値の対応はたいてい0という文字の次に1, 2, ..., 9と続くようになっています。……でもあなたの処理系で本当に連続して並んでいますか?将来そのように並んでない処理系への移植がないと100%言い切れますか?

これは、0から9までの数値をそれに対応する文字に変換するお手軽かつ問題のある手法です。

ご存知かもしれませんが、コンピューターでは文字は内部的には対応する数値で表されています。
ですから、C/C++ではchar形の中にあるのは文字ではなくその文字に対応する数値です。
したがって、
sequence + '0'
は0という文字を表す数値にsequenceを足した値になります。文字と数値の対応はたいてい0という文字の次に1, 2, ..., 9と続くようになっていますので、結果、sequenceが0なら0という文字を表す数値、sequenceが...続きを読む

Qオーバーロードされたメンバ関数のポインタをとる

オーバーロードされたメンバ関数のポインタをとるにはどうしたらよいでしょうか?
具体的には前置インクリメント演算子 ++()と、後置インクリメント演算子 ++(int)の両方のをオーバーロードしたときに両方のメンバ関数ポインタがとりたいです。
環境はVC7.1です。
よろしくお願いします。

Aベストアンサー

クラス X に対して前置/後置インクリメントはそれぞれ
X &X::operator ++();
X operator ++(int);
と定義するのが普通なので, それにあわせて
X &(X::*preinc)() = &X::operator++;
X (X::*postinc)(int) = &X::operator++;
でとれないですかね? Visual Studio 2008 だとこれでいけるんですが.

Qilink32について。'__setargv__'と'__turboFloat__'が未解決

WindowsXP+bcc32+ilink32でGLUTを使ったプログラムを書いています。
bccの設定はsetbcc.exe(http://www.cmagazine.jp/setbcc.html)を使いました。
opengl32.lib, glu32.lib, glut32.libはimplib.exe(http://blog.jyoken.net/?eid=478291)を使って作成しました。

以上の設定でbcc32付属のMakeを使ってmakeしたところ、
コンパイル後のリンクで以下のようなエラーが出てしまい困っています。
どなたか解決法を教えていただけないでしょうか?

よろしくお願いします。


---------------------
エラーの内容
---------------------
Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland
Error: 外部シンボル '__setargv__' が未解決(root が参照)
Error: 外部シンボル '__turboFloat' が未解決(root が参照)
---------------------

---------------------
使用しているMakefile
---------------------
CC= bcc32
LINKER= ilink32

SRCS= main.c callback.c Task.c Logger.c
OBJS= $(SRCS:.c=.obj)
TARGET= main.exe

CFLAGS= -wall -O2
LFLAGS=
LIBS= opengl32.lib glu32.lib glut32.lib

INCLUDE= -I"C:\borland\bcc55\Include"
LIB= -L"C:\borland\bcc55\Lib"


all: $(TARGET)

.SUFFIXES : .obj .c

.c.obj:
$(CC) $(CFLAGS) -c $(SRCS)

$(TARGET): $(OBJS)
$(LINKER) $(LFLAGS) $(LIB) $(OBJS),$(TARGET),,$(LIBS)
---------------------

WindowsXP+bcc32+ilink32でGLUTを使ったプログラムを書いています。
bccの設定はsetbcc.exe(http://www.cmagazine.jp/setbcc.html)を使いました。
opengl32.lib, glu32.lib, glut32.libはimplib.exe(http://blog.jyoken.net/?eid=478291)を使って作成しました。

以上の設定でbcc32付属のMakeを使ってmakeしたところ、
コンパイル後のリンクで以下のようなエラーが出てしまい困っています。
どなたか解決法を教えていただけないでしょうか?

よろしくお願いします。


---------------------
エラー...続きを読む

Aベストアンサー

BorlandのCコンパイラは、スタートアップルーチンを含むオブジェクトファイルは
ライブラリファイルの中にはアーカイブされていなくて、適切な
スタートアップ用.objファイルを別途指定してリンクしていたと思います
#bcc32.exeを使った場合はコンパイラドライバが自動でやってくれる。

質問にあるMakefileの内容を見た感じでは、そのOBJファイルを指定していませんので、
それが原因で解決できないシンボル名がでているのだと思います。
ということで、ilink32.exeでリンクする対象にそのスタートアップ用OBJファイルを
含めてやればよろしいかと。

C0なんとか.OBJという名前で、コンパイルオプションに応じていくつか
存在していたと思います。
#置かれている場所はライブラリファイルのあるディレクトリです。

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

こんにちは。お世話になっております。

// +演算子オーバーロード
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;だけで計算出来るプログラムを教えてください。

こんにちは。お世話になっております。

// +演算子オーバーロード
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()...続きを読む

Aベストアンサー

CPoint CPoint::operator+(CPoint& obj)
ひとつ用意すれば
連続して3つでも4つでも、いくつでも加算可能です。

Qif文の判定条件('||'と'&&'の使い方)

○if文の判定条件への理解が弱いため、下記プログラムを作成し、
疑問があったため、質問をしたいと思っております。

#include<stdio.h>
#include<string.h>

int main()
{
char moji[]= "A";
/***********************************************************/
if( 0 != strcmp( moji , "A" ) || strcmp( moji , "B" ) )
^^(1)
/***********************************************************/
{
printf( "文字不一致" );
}
else
{
printf( "文字一致" );
}

return (0);
}

○質問
「/*/」で囲ったif文の判定箇所になりますが、
この判定条件は"配列mojiに格納されている値が"A",または"B"以外の"
ときに、画面上に「文字不一致」を出力します。そうでなければ
「文字一致」を出力します。

今回、配列mojiには"A"が格納されており、「文字一致」が画面に
出力されるはずですが、「文字不一致」が出力されてしまいます。

判定条件が誤っていると思い、色々と試したところ、(1)の箇所を
「&&」にしたときに、「文字不一致」が出力されます。

「||」(論理和)と「&&」(論理積)が理解できていないと思われ、
この部分を交えて、何故「&&」にしないと「画面不一致」と出力
されないのかを、ご教授の程お願い致します。

○if文の判定条件への理解が弱いため、下記プログラムを作成し、
疑問があったため、質問をしたいと思っております。

#include<stdio.h>
#include<string.h>

int main()
{
char moji[]= "A";
/***********************************************************/
if( 0 != strcmp( moji , "A" ) || strcmp( moji , "B" ) )
^^(1)
/***********************************************************/
{
printf( "文字不一致" );
}
else
{
printf( "文字一致" );
}

...続きを読む

Aベストアンサー

No.3 です。

---------------------------
(1)は配列mojiにAが格納されていない場合
(2)は配列mojiにBが格納されていない場合

《 略 》

(3)では(1)と(2)で出力された値の論理積(偽と真の論理積)を取り、
偽となるので、else側に移り、「文字一致」が出力される。
---------------------------
この理解で、考え方としては合っています。
普段はこれでOKです。

ただ、C言語ではもうひとつ別の問題があります。
No.4 の方の回答でも触れられていますが。

もともと、&& や || の性質として、
&& が、「真」になるのは、両方が真の時だけ、つまり、左側が「偽」なら、右側が何であっても、「偽」
|| が、「偽」になるのは、両方が偽の時だけ、つまり、左側が「真」なら、右側が何であっても、「真」
という事があります。

C言語ではこれを積極的に取り入れており、
1) && は、左側が「偽」であれば、右側は調べなくても全体として「偽」になるに決まっている。したがって、右側は調べない。
2) || は、左側が「真」であれば、右側は調べなくても全体として「真」になるに決まっている。したがって、右側は調べない。

という動きをします。
ですから、このケースでは、(1)の部分が「偽」となった時点で、全体が偽になるのが明らかです。ですから、(2)の部分は、調べません。

よって、C言語の動きに沿っていえば、
(1)の部分が「偽」となる。だから、((2)を調べるまでもなく)(3)全体として、「偽」となり、else 部分が実行される
という流れになります。

もっとも、これは、結果としては真偽表と矛盾はしないので、補足にお書きになったような理解でも普通はかまいません。
ただし、&& や || 以降の部分を調べることが、他の影響を与える時(例えば、strcmp() の中に(たとえ話です)「一致した」とかいう出力を行う部分があったら、この出力が1回しかでなかったり(&& の前で「偽」が決定した時)2回出たり(&& の前が「真」だったので、後ろも調べた時)というように、この影響を考慮しなければならない場合もあります。

No.3 です。

---------------------------
(1)は配列mojiにAが格納されていない場合
(2)は配列mojiにBが格納されていない場合

《 略 》

(3)では(1)と(2)で出力された値の論理積(偽と真の論理積)を取り、
偽となるので、else側に移り、「文字一致」が出力される。
---------------------------
この理解で、考え方としては合っています。
普段はこれでOKです。

ただ、C言語ではもうひとつ別の問題があります。
No.4 の方の回答でも触れられていますが。

もともと、&& や || の性質として、
...続きを読む


人気Q&Aランキング

おすすめ情報