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其制成 aconst string并没有帮助。我能够通过使用来让它工作str.c_str(),但是有人可以帮助我理解为什么const -ness 在文件打开方法中被强制执行吗?为什么不应该允许我按原样使用字符串,而不必使用 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++0xstd=c++11 标志启用)

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

不会对非常量字符串对象造成任何问题。

const string &有助于避免不必要的字符串对象复制

于 2013-10-25T17:22:39.203 回答
2

您的代码使用当前标准(C++11)编译得很好,遗憾的是我所知道的任何编译器都默认不使用该标准。

于 2013-10-25T17:25:48.067 回答
2

open接受 a的事实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*(例如一个指向常量字符数组的指针)。第二个重载采用一个const std::string&(例如对常量 std::string 的引用)。

它不是const std::string,而是对字符串的引用。它说明该函数不会修改字符串,并且您正在传递对原始字符串的引用(而不是复制它)。您可以将非常量字符串传递给需要 const 字符串的函数而不会出现问题(不需要转换/转换)。

您最初的问题(为什么需要一个const char*?)的答案并不那么复杂:流库和字符串库是由不同的人群并行开发的。在早期的标准中,他们没有合并开发。这已在 C++11 中解决。

于 2013-10-25T17:56:32.940 回答