17

以下がうまくいかない理由を誰かが答えてくれることを願っています。我慢してください、私はまだ非常に初心者です...私は、なぜ次の

using namespace std;
#include <string>
#include <iostream>

class testClass
{
public:
 operator char* () {return (char*)"hi";};
 operator int ()  {return 77;};
 operator std::string  () {return "hello";};
};

int main()
{
 char* c;
 int i;
 std::string s = "goodday";

 testClass t;

 c = t;
 i = t;
 s = t;

 cout<< "char: " << c << " int: " << i << " string: "<<s<<endl;

 return 0;
}

コンパイル時エラーが発生します:

myMain.cpp: In function ‘int main()’:
myMain.cpp:23: error: ambiguous overload for ‘operator=’ in ‘s = t’
/usr/include/c++/4.2.1/bits/basic_string.h:500: note: candidates are: std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT, _Traits, _Alloc>::operator=(const std::basic_string<_CharT, _Traits, _Alloc>&) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]
/usr/include/c++/4.2.1/bits/basic_string.h:508: note:                 std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT, _Traits, _Alloc>::operator=(const _CharT*) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]
/usr/include/c++/4.2.1/bits/basic_string.h:519: note:                 std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT, _Traits, _Alloc>::operator=(_CharT) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]

課題をやらないと

s = t;

それは機能します。

私はエラーメッセージを理解するために何時間も努力してきましたが、私を最も困惑させているのは、それがchar *で機能することです.

ヒントに感謝します。ありがとう!マーカス

4

5 に答える 5

13

エラーが説明しようとしているのは、あなたの割り当て " s = t"、ここsで aは、あまりにも、または[ ]だったstd::string場合に有効になるということです。変換演算子は aをどちらかに変換できるため、コンパイラにはどちらを選択するかの根拠がありません....tstd::stringtconstchar*t

必要な変換を選択することで、これを明示的に明確にすることができます。

s = t.operator std::string();
s = static_cast<std::string>(t);

または、1 つの変換のみを提供し、必要に応じてユーザーがさらに変換できるようにすることもできます。

ただし、最終的には、変換演算子は価値があるよりも面倒であることに気付くかもしれません...それstd::string自体が への変換演算子を提供していないことを示していますconst char*

于 2010-08-19T01:56:52.753 に答える
9

$13.3.1.5/2 は次のように述べています-「S とその基本クラスの変換関数が考慮されます。S 内に隠されておらず、型 T または標準の変換シーケンス (13.3.3.1 .1) は候補関数です. cv 修飾された型を返す変換関数は、候補関数を選択するこのプロセスのために、その型の cv 修飾されていないバージョンを生成すると見なされます. 「cv2 X への参照」を返す変換関数は、型の左辺値を返します「cv2 X」であるため、候補関数を選択するこのプロセスで X を生成すると見なされます。

代入 s = t は次のように機能します。

a) 't' (testClass) の型のすべてのメンバーが考慮され、't' を 's' に変換できます。

Candidate 1: operator string();   // s created using member string::operator=(string const&)
Candidate 2: operator char *()    // s created using member string::operator=(char const*)
Candidate 3: operator char *()    // s created using member string::operator=(char *)

b) 上記の候補はすべて実行可能です (つまり、他の候補がない場合、コンパイラはそれらのいずれかへの関数呼び出しを正常に解決できます)。

c) ただし、実行可能な最良の候補を決定する必要があります。関連する変換シーケンスは次のとおりです。

Candidate 1: U1 : operator string()
Candidate 2: U2 : operator char*()->const qualification to match string::operator=(char const*)
Candidate 3: U3 : operator char*()

$13.3.3.1.1/3 の状態 - 「変換シーケンスのランクは、シーケンス内の各変換のランクと参照バインディングのランクを考慮して決定されます (13.3.3.1.4)。それらのいずれかに変換ランクがある場合、シーケンスはコンバージョン ランクを持っています。"

これは、U1、U2、および U3 がすべてコンバージョン ランクを持ち、最初のレベルではどちらも他より優れていないことを意味します。ただし、規格には次のようにも記載されています。

ユーザー定義変換シーケンス U1 は、同じユーザー定義変換関数またはコンストラクターを含み、U1 の 2 番目の標準変換シーケンスが U2 の 2 番目の標準変換シーケンスよりも優れている場合、別のユーザー定義変換シーケンス U2 よりも優れた変換シーケンスです。 .

それでは、これが何を意味するのか見てみましょう。

U1 と U2 の間には、異なる変換機能が含まれているため、他よりも優れているものはありません。

U1 と U3 の間には、異なる変換機能が含まれているため、どちらも優れていません。

では、U1 と U2 はどうでしょうか。これらは、上記の「and」条件の最初の部分を満たす同じ変換関数を含みます。

では、「U1 の 2 番目の標準変換シーケンスが U2 の 2 番目の標準変換シーケンスよりも優れている場合」の部分はどうでしょうか。

U2 では、2 番目の標準変換シーケンスに const 修飾が必要ですが、U3 ではこれは必要ありません。U3 の 2 番目の標準変換シーケンスは完全一致です。

ただし、標準の表 9 にあるように、CV 資格も完全一致と見なされます。

したがって、過負荷の解決を考慮する限り、U2 と U3 も実際には区別できません。

これは、U1、U2、および U3 がすべて実際に相互に優れていることを意味し、コンパイラーは呼び出しを (代入ステートメントの一部として) あいまいなものとして解決することを検出します

于 2010-08-19T02:46:19.110 に答える
3

正確な std::string::operator= はありません。候補は、言い換えると、

s = (const std::string)(std::string)t;
s = (const char*)t;
s = (char)(int)t;

const std::string を返すように変更するとうまくいくと思います。編集:私は間違っています。)また、最初の関数は const char * を返す必要があることに注意してください。文字列リテラルを char* にキャストする必要がある場合は、何か問題があります。文字列リテラルは書き込み可能ではありません。

于 2010-08-19T02:00:59.310 に答える
1

実際、それstd::stringは、 を取る代入演算子を提供しているためconst char*です。

于 2010-08-19T01:54:47.587 に答える
0

よし、もうみんなどうもありがとう。コツをつかみ始めていると思います...

まず第一に、char が単なる 8 ビットの int であるという事実を知りませんでした。その説明をありがとう。

std::string には 3 つの代入演算子が定義されており、それぞれに異なる引数 (string、char*、const char*) が式の右側にあることを理解しています。

s=t

いずれかで定義された複数の潜在的に一致する (この std::string への割り当て) 変換があるため、どの型に変換する必要があるかわかりません

operator int ()  {return 77;};
operator std::string  () {return "hello";};

(char : 8bit int であるため)

また

operator char* () {return (char*)"hi";};
operator std::string  () {return "hello";};

そうですか?つまり、ばかげた言葉で言えば、代入の左側は右側に期待する型を伝えていないので、rhs はそのオプションから選択する必要があります。std::string operator= は私の意図に対して寛容ですか?

これまでのところ、私はそれを理解していると思っていました.

 using namespace std;
 #include <string>
 #include <iostream>

 class testClass
  {
   public:
     operator float ()  {return float(77.333);};
     operator std::string  () {return "hello";};
  };

  int main()
  {
    std::string s = "goodday";
    testClass t;

    s = t;

    cout<< " string: "<<s <<endl;

    return 0;
  }

今、私が定義した一致する変換演算子は 1 つだけですよね? std::string operator= は float を取ることができませんか? それとも、float は何らかの形で char の変種と同等ですか?

私はコードを 's=' として rhs に伝えていることを理解しています: "文字列、char* または const char* をください"

Rhs は、与えられた testClass のインスタンスで提供できるものをチェックし、一致するのは testClass::operator std::string のみです。

繰り返しますが、あなたの忍耐、専門知識、時間のおかげで、本当に感謝しています.

于 2010-08-19T05:30:17.040 に答える