类构造函数“C2248:'std :: basic_ios< _Elem,_Traits> :: basic_ios':无法访问类'std :: basic_ios< _Elem,_Traits>'中声明的私有成员

时间:2012-12-19 15:40:58

标签: c++ visual-studio-2010 stl ansi

这是我的第一篇文章。

我阅读了很多主题,似乎我做得很好,但是当我尝试编译以下代码时,我再次遇到上述错误:

// Header file

#include <fstream>
#include <ostream>
#include <string>

using namespace std;

class CLogger
{
private:
    ostream m_oStream;

public:
    CLogger(ostream& oStream);
    CLogger(const string sFileName);
};

// Implementation file

CLogger::CLogger(ostream& oStream) : 
m_oStream(oStream) // <-- Here is the problem?!
{
}

CLogger::CLogger(const string sFileName) :
    m_oStream(ofstream(sFileName.c_str()))
{   
}

你能帮帮我吗?

非常感谢!

2 个答案:

答案 0 :(得分:6)

CLogger::CLogger(ostream& oStream) : // <-- Here is the problem?!
m_oStream(oStream)

问题不在第一行,而是在第二行。

由于成员m_oStream被声明为非引用,因此上面的第二行尝试复制oStream这是不可能的,因为std::ostream的复制构造函数被禁用通过使其成为private,这是您在错误消息中看到的“无法访问私有成员。”

解决方法是:

std::ostream * m_oStream; //declare it as pointer.
bool m_deleteStream;      //flag whether to delete m_oStream or not

现在这样做:

CLogger::CLogger(ostream& oStream) : 
m_oStream(&oStream), m_deleteStream(false)
{
}

CLogger::CLogger(const string sFileName) :
m_oStream(new std::ofstream(sFileName)), m_deleteStream(true)
{
  //Note : in C++03, you've to pass sFileName.c_str() to 
  //the constructor of std::ostream   
}

然后你要把析构函数写成:

~CLogger()
 {
    if ( m_deleteStream )
    {
        delete m_oStream;
    }
 }

重要的一点是:由于这是一个资源管理(记录器)类,因此不可复制是一个好主意,因为复制对记录器实例没有意义。

答案 1 :(得分:0)

m_oStream(ofstream(sFileName.c_str()))

您构建ofstream并使用它复制构建您的m_oStream。只需写下

m_oStream(sFileName.c_str())

Streams既不是可复制的也不是可复制的,虽然它们是可移动的类型,所以我猜你的在这个例子中使用C ++ 11。

出于同样的原因,

CLogger::CLogger(ostream& oStream) : 
    m_oStream(oStream)

无法运作。你不能制作副本,你只能移动(在C ++ 11中)或持有某种形式的引用。


旁注:

从您的示例中,您是否这样做并不完全清楚,但不要忘记在头文件中包含警戒。