2

だから私はこのサンプルコードを実行しています:

#include<iostream>
#include<fstream>
#include<string>
using namespace std;
int main() {

  ifstream inFile;
  string str;

  cout << "\nEnter file name : ";
  cin >> str;

  try {
    inFile.open(str);
    if(!inFile)
      throw exception();
  } catch(exception e) {
    cout <<"\nAn exception was caught. file does not exist. ";
    return 1;
  }

  return 0;
}

そして、それは私にコンパイラエラーを与えました:

test.cpp:14:13: error: no viable conversion from 'string' (aka 'basic_string<char>') to 'const char *'
inFile.open(str);
            ^~~
/usr/include/c++/4.2.1/fstream:517:24: note: passing argument to parameter '__s' here
      open(const char* __s, ios_base::openmode __mode = ios_base::in)

関数プロトタイプを調べました:

void open (const char* filename,
           ios_base::openmode mode = ios_base::in | ios_base::out);
void open (const string& filename,
           ios_base::openmode mode = ios_base::in | ios_base::out);

fstream::open() が const String/ const char* を期待するのはなぜですか? ファイル名はどこからでも (上記の例のようにユーザーから) 取得することができ、その場合は を作成strしてconst stringも役に立ちません。代わりに使用して動作させることができましたが、ファイルを開くメソッドでconststr.c_str()ネスが強制されている理由を誰かが理解するのを手伝ってくれませんか? char* を使用したり、C スタイルの文字列に変換したりせずに、文字列をそのまま使用することを許可しないのはなぜですか?

4

5 に答える 5

6

const参照を取る関数に非オブジェクトを渡すことができconstます。

問題は、C++11 のサポートがない (または有効になっていない) ため、stringオーバーロードが見つからないことです。2011 年より前のライブラリに行き詰まっている場合、唯一のオプションはc_str()、C スタイルの文字列ポインターを取得するために使用することです。

于 2013-10-25T17:21:30.203 に答える
3

C++11 (-std=c++0xまたはstd=c++11 フラグで有効化)

void open (const string& filename,
           ios_base::openmode mode = ios_base::in | ios_base::out);

非 const 文字列オブジェクトでは問題は発生しません。

文字列オブジェクトの不要なコピーを避けるのconst string &に役立ちます

于 2013-10-25T17:22:39.203 に答える
2

openがかかるという事実は、const char*それを通常の に渡すことができないという意味ではありませんchar*char*に変換できますがconst char*、その逆はできません ( を使用しない限りconst_cast、しかしそれらは悪です)。

この宣言は、「open文字列を入力として取り、内容を変更しないことを約束する」と言っているだけです。

于 2013-10-25T17:22:49.610 に答える
1

関数シグネチャの構文を誤解しています:

fstream::open() が const String/ const char* を期待するのはなぜですか? ファイル名はどこからでも (上記の例のようにユーザーから) 取得でき、その場合は str を const 文字列にしても役に立ちません。

署名は参照用に以下に示します。

void open (const char* filename, ios_base::openmode mode = ios_base::in | ios_base::out);
void open (const string& filename, ios_base::openmode mode = ios_base::in | ios_base::out);

最初のオーバーロードはconst char*(定数文字配列へのポインタなど) を取ります。2 番目のオーバーロードはconst std::string&(定数 std::string への参照など) を取ります。

const std::stringではなく、文字列への参照です関数が文字列を変更しないことを示しており、元の参照を (コピーするのではなく) 渡しています。const 文字列を必要とする関数に非 const 文字列を問題なく渡すことができます (変換/キャストは必要ありません)。

元の質問 (なぜ が必要なのconst char*ですか?) に対する答えはそれほど複雑ではありません。ストリーム ライブラリと文字列ライブラリは、さまざまなグループの人々によって並行して開発されました。初期の標準では、開発をマージしませんでした。これは C++11 で対処されています。

于 2013-10-25T17:56:32.940 に答える