【问题标题】:Why I cannot create and open an ofstream in the same code line?为什么我不能在同一代码行中创建和打开 ofstream?
【发布时间】:2019-03-24 07:51:54
【问题描述】:

我能做到:

std::ofstream outfile; outfile.open("foo");

但不是:

std::ofstream outfile.open("foo");

因为它给出了这个错误:

error: expected ';' at end of declaration
    std::ofstream outfile.open("foo");
                         ^

您也可以在 Live Demo 中看到。

为什么?

PS:我知道我可以std::ofstream outfile("foo");,但我怀疑我缺少 C++ 的机制,这就是我问的原因。

【问题讨论】:

  • 如果你想知道为什么在对象构造中不允许成员调用,你选择了非常糟糕的例子。因为 90% 的答案是 - 您可以将名称传递给 ctor。
  • 这个例子选择了我@Slava。 ...正如答案部分所证明的那样,您是对的。
  • @Slava "you can pass name to ctor" 嗯,不,不是真的......你不能命名构造函数,也不能直接“调用”它声明或初始化程序。
  • @LightnessRacesinOrbit 我很确定 Slava 的意思是使用构造函数打开文件,通过将文件名作为构造函数的第一个参数传递。
  • @gsamaras 你说得对,我的意思确实是文件名。

标签: c++ file oop fstream ofstream


【解决方案1】:

为什么?

因为语言不允许将声明与成员函数调用结合起来。变量outfile 甚至在声明之后才存在。

使用构造函数打开文件:

std::ofstream outfile("foo");

【讨论】:

  • 我知道构造函数。答案是这样的:“因为语言不允许将声明与成员函数调用结合起来。”,这将是很好的参考,或其他东西。哦,好吧,您的编辑有帮助!
  • @gsamaras 如果你已经知道构造函数,而且我们都知道你知道,我不明白你为什么问这个问题。
  • @gsamaras 你找不到明确的参考。该语言是以特定方式设计的,如果有允许相关代码的动机,那么也许会有办法做到这一点,但我不明白你为什么需要它。它基本上是在问“为什么我的车没有喷气发动机,手册并没有说它必须丢失”。同样的推理 - 通常不需要它,并且会使事情变得比它们必须的更复杂。你可以创造一辆拥有它的汽车(这不是不可能的),但它会是一辆完全不同的汽车,用于非常不同的目的。
【解决方案2】:

这类似于当您有一个返回对象的函数并且您想在同一行中调用它的方法时:

struct foo { void bar(){} };
foo create_foo() { return foo(); }

您可以存储create_foo 的结果或使用其返回值调用方法,但不能同时使用这两种方法:

create_foo().bar();          // OK
auto f = create_foo();       // OK
auto f = create_foo().bar(); // NOPE

ofstream:你可以写

std::ofstream().open("foo");

但您没有机会获得对ofstream 的引用。

【讨论】:

  • 我没有测试过,但我猜如果bar() 返回了一些东西(不是void),那么第三种情况实际上会做一些事情。也许不是预期的,但它会起作用。
  • @KevinAnderson 是的。如果bar 将返回对*this 的引用,甚至可以获取引用并在同一行中调用方法,但std::ofstream::open() 并非如此
【解决方案3】:

因为你不能。

说真的。

C++ 有允许的语法,你不能编写不遵守它的代码。

声明/表达式混合的用例为零,在尚不存在的对象上使用 void-returning 成员函数,并且没有初始化程序的 =

但你已经知道了。

【讨论】:

    【解决方案4】:

    我猜你已经习惯了 Java 或 C# 之类的东西,这种类型的事情是可能的:

    BufferedReader br = new BufferedReader(new FileReader(FILENAME));
    

    甚至是 Python:

    lines = open("filename").readlines();
    

    这里的诀窍是,使用正确的“工厂函数”,您也可以在 C++ 中执行此操作,但这不是这个特定类的制作方式。上面的其他示例,其中之一:

    std::ofstream outfile{"foo"};
    auto outfile = std::ofstream("foo");
    

    是在 C++ 中执行此操作的“正常”方式。部分断开连接是 open() 方法返回 void:std::basic_ofstream::open() doc。所以当你有这个代码时:

    std::ofstream outfile.open("foo");
    

    它无法编译,因为 open() 是一个成员函数(不是静态的)并且它返回 void 而不是 std::ofstream,这是你声明你正在做的。

    我希望这能为你解决问题。

    【讨论】:

    • 这种猜测与凯文的错误相去甚远。 :/ 是的,确实很有帮助。
    • 好吧,你赢了一些,你也输了一些。但希望无论如何它都会有所帮助。
    • 即使open() 返回std::ofstream,它仍然无效,因为该行是声明和表达式的奇怪混合,没有引入初始化程序。我真的不明白知道 C++ 的 gsamaras 想要解决这个问题。
    • @LightnessRacesinOrbit 以更好地掌握和理解该语言,如果这个问题听起来很愚蠢,对不起......
    • @LightnessRacesinOrbit 我知道即使open() 以不同的方式返回也行不通,他们需要auto outfile = std::ofstream::open("foo.txt"); 不存在。但如果有这样的工厂,他们会没事的。
    【解决方案5】:

    你可以这样做:

    std::ofstream outfile { "foo" };
    

    【讨论】:

      【解决方案6】:

      因为语言。 C++ 不允许这样的指令。

      使用构造函数

      std::ofstream outfile("foo");

      或初始化

      std::ofstream outfile { "foo" };

      【讨论】:

      • 仅供参考,这些都是 both 使用构造函数初始化
      【解决方案7】:

      但不是:

      std::ofstream outfile.open("foo");

      这是一个简单明了的语法错误。此时,outfile 被解释为某个未定义对象的名称。编译器根本不明白您要创建ofstream 类型的对象。

      我们可能天真地希望我们可以像这样简单地修复它:

      auto outfile = std::ofstream().open("foo"); // call open on a constructed object.
      

      问题是open 方法没有返回ofstream 的副本,所以这不起作用。 (它实际上返回 void)。

      可行的方法:

      // unexciting, but simple - uses a different constructor
      std::ofstream outfile{"foo"};
      

      这(恕我直言)更具可读性和合法性:

      auto outfile = std::ofstream("foo");
      

      【讨论】:

      • 有钱,我知道!我想知道为什么我尝试的方法不起作用,如果您可以将答案编辑到那个方向,那就太好了!
      • @gsamaras 是的,我明白了。我会考虑是否可以提供更多见解。
      猜你喜欢
      • 1970-01-01
      • 2015-04-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多