c++ - VC 选择错误的 operator<< 仅在第一次调用时重载。漏洞?

标签 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;
};

--- 文件.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"和运行

--- 测试.txt ---

00414114test

基本上发生的是第一个 operator<<来电main绑定(bind)到成员方法

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

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

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

从而给出不同的输出。

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

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

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

这有什么解释吗?

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

感谢任何帮助甚至线索

最佳答案

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

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

但是,编译器有权这样做,因为您有

    void main()

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

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

关于c++ - VC 选择错误的 operator<< 仅在第一次调用时重载。漏洞?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1971271/

相关文章:

c++ - MSVC10/11 中缺少统一初始值设定项的宏/内联函数解决方法

c++ - 隐式转换运算符重载语法

python - 是否可以在 Python 中重载逻辑和?

python - 何时在 python 中使用运算符重载的经验法则

javascript - 将 JavaScript split()-slice()-join() 序列转换为 C++

c++ - 在初始化列表中复制对象

c++ - 在 C++14 中 [class]/7 中的要点 (7.5) 的目的是什么?

c++ - 连接 Boost Hana 字符串

c++ - 使用 Visual Studio 创建 C++ DLL

windows - fopen 使用 unicode 文件名