覆盖流运营商<<

时间:2015-03-28 21:17:07

标签: c++

为什么我仍然在下面一行的std::ofstream << val中有错误:预期标识符? MSVC。

std::ostream& operator<< (bool val) { m_lock.lock(); std::ofstream << val; m_lock.unlock(); return *this; }
class OfstreamLog : public std::ofstream  {

    private:

        std::mutex m_lock;

    public:

        OfstreamLog() : std::ofstream() { }
        explicit OfstreamLog(const char* filename, ios_base::openmode mode = ios_base::out) : std::ofstream(filename, mode) { }

        std::ostream& operator<< (bool val) { m_lock.lock(); std::ofstream << val; m_lock.unlock(); return *this; }
        std::ostream& operator<< (short val);
        std::ostream& operator<< (unsigned short val);
        std::ostream& operator<< (int val);
        std::ostream& operator<< (unsigned int val);
        std::ostream& operator<< (long val);
        std::ostream& operator<< (unsigned long val);
        std::ostream& operator<< (float val);
        std::ostream& operator<< (double val);
        std::ostream& operator<< (long double val);
        std::ostream& operator<< (void* val);
        std::ostream& operator<< (std::streambuf* sb);
        std::ostream& operator<< (std::ostream& (*pf)(std::ostream&));
        std::ostream& operator<< (std::ios& (*pf)(std::ios&));
        std::ostream& operator<< (ios_base& (*pf)(ios_base&));

    };

1 个答案:

答案 0 :(得分:7)

std::ofstream是类型名称。你不能在没有任何对象的情况下调用非静态方法或操作符。

在这种情况下,您可能需要std::ofstream::operator<<(val);而不是std::ofstream << val;


<强>解释

当您想从子类的方法调用父类的方法时,您可以这样做:

class A
{
    void func() {}
};

class B
{
    void test()
    {
        func(); // Like this
    }
};

但是如果子类具有相同名称的方法(更准确地说,具有相同的签名(它意味着相同的名称和参数类型)),它将被调用而不是父类的一个。要显式调用父类的方法,可以使用以下语法:

class A {...};
class B
{
    void test()
    {
        A::func(); // Notice `A::`
    }
};



现在让我们谈谈运营商。如果要调用运算符,通常会使用对象名称,例如object << 10;。但是当你想从这个类的方法调用一个类(或它的父类)的操作符时,你应该使用完整的operator语法:

class A
{
    operator<<(int){}
};
class B
{
    void test()
    {
        operator<<(10); // <-----
        *this << 10; // Also you can do it like this
    }
};



现在,我们将这两种技术结合起来:
如果子类具有与父级别相同的签名操作符并且您想要调用父级的操作符,则可以这样执行:

class A {...};
class B
{
    void test()
    {
        A::operator<<(10); // Notice `A::`
        *(A*)this << 10; // Also you can do it like this
    }
};