VC选择错误的运算符<<仅在第一次通话时过载。错误?

时间:2009-12-28 20:04:27

标签: c++ visual-c++ operator-overloading c++-standard-library

我花了一些时间删除所有不流畅的代码,这是我的问题。

--- File.h ---

#include <fstream>
#include <string>

template <typename Element>
class DataOutput : public std::basic_ofstream<Element>
{
public:
    DataOutput(const std::string &strPath, bool bAppend, bool bBinary)
    : std::basic_ofstream<Element>(
        strPath.c_str(),
        (bAppend ? ios_base::app : (ios_base::out | ios_base::trunc)) |
(bBinary ? ios_base::binary : 0))
    {
        if (is_open())
            clear();
    }

    ~DataOutput()
    {
        if (is_open())
            close();
    }
};


class File 
{
public:
    File(const std::string &strPath);

    DataOutput<char> *CreateOutput(bool bAppend, bool bBinary);
private:
    std::string m_strPath;
};

--- File.cpp ---

#include <File.h>

File::File(const std::string &strPath)
: m_strPath(strPath)
{
}

DataOutput<char> *File::CreateOutput(bool bAppend, bool bBinary)
{
    return new DataOutput<char>(m_strPath, bAppend, bBinary);
}

--- main.cpp ---

#include <File.h>

void main()
{
    File file("test.txt");

    DataOutput<char> *output(file.CreateOutput(false, false));

    *output << "test"; // Calls wrong overload
    *output << "test"; // Calls right overload!!!

    output->flush();
    delete output;
}

这是使用cl和选项/D "WIN32" /D "_UNICODE" /D "UNICODE"构建并运行

后的输出文件

--- test.txt ---

00414114test

基本上发生的事情是operator<<中的第一个main调用绑定到成员方法

basic_ostream<char>& basic_ostream<char>::operator<<(
    const void *)

而第二个(正确地)绑定到

basic_ostream<char>& __cdecl operator<<(
    basic_ostream<char>&,
    const char *)

因此给出了不同的输出。

如果我执行以下任何操作,则不会发生这种情况:

        
  • 内联File::CreateOutput
  •     
  • 使用DataOutput
  • 的非模板工具更改Element=char     
  • 在第一次*output;来电之前添加operator<<

我认为这是一种不受欢迎的编译器行为吗?

对此有任何解释吗?

哦,我现在正在使用VC7来测试这个简化的代码,但我已经尝试了VC9和VC8中的原始代码,同样的事情正在发生。

感谢任何帮助甚至是线索

3 个答案:

答案 0 :(得分:3)

这是一个编译器错误(不仅仅看起来像一个),因为它为两个相同的语句产生不同的调用绑定

    *output << "test"; // Calls wrong overload
    *output << "test"; // Calls right overload!!!

然而, 编译器在其权利 范围内执行此操作,因为您有

    void main()

这意味着这不是一个有效的C ++程序(C中也不允许void main,并且它在C或C ++中从未有效)。因此,您一直在运行编译无效源代码的结果。结果可以是任何事情。

Visual C ++编译器未诊断void main的事实只是 另一个编译器错误

答案 1 :(得分:2)

看起来像编译器错误。您可能想尝试使用最新的VC编译器(目前是VC10 Beta2),如果没有修复,请跟进VC团队(您需要一个完整的自包含仓库)。如果它是固定的,你应该只使用你周围的工作,继续你的生活。

答案 2 :(得分:0)

变化

DataOutput *输出(file.CreateOutput(false,false));

DataOutput * output = file.CreateOutput(false,false);它可能会奏效。但是为了使它成为一个合理的lib函数,你不必在不应该返回指针而是实际对象之后进行清理。