为什么Visual C++ 6会抱怨私有析构函数?

5
以下代码适用于Visual C++ 2008,但在Visual C++ 6中出现以下错误。请问为什么会出错,我该如何解决这个问题并使析构函数仍处于私有状态?
class X
{
public:
    static X& instance()
    {
        static X database;
        return database;
    }

private:

    X() {}                    // Private constructor
    ~X() {}                   // Private destructor
    X(const X&);              // Prevent copy-construction
    X& operator=(const X&);   // Prevent assignment
};

int main()
{
    X::instance();
}

C:\Projects\ttt6\main.cpp(178) : error C2248: 'X::~X' : 无法访问已在类“X”中声明的私有成员 C:\Projects\ttt6\main.cpp(175) : 参见“X::~X”的声明


3
构造函数并不总是应该设置为公共的。举例来说,对于一个抽象类,你只希望派生类调用它的构造函数(这样可以防止抽象类被实例化),因此将其设置为protected。对于单例模式,你希望只有类的静态CreateInstance()方法才能创建一个实例,因此需要将构造函数设置为private - Scott Smith
2
这段代码在VC9上也会出错。我无法相信它能在任何编译器上编译通过。 - Naveen
这在任何编译器中都无法编译。 - GManNickG
1
VC2008是VC9。VC6等同于VC98,VC7等同于VC2002,VC7.1等同于VC2003,VC8等同于VC2005,VC9等同于VC2008,VC10等同于VC2010。 - GManNickG
此外,这就是为什么提供实际、可工作和可编译的代码示例比其他变体更重要的原因。否则我们就不在解决同一个问题了。 :) - GManNickG
显示剩余3条评论
4个回答

7
修改后的示例显示了VC6中的已确认的编译器错误 - 常见的解决方法是将析构函数简单地设置为公共的。

你有关于这个 bug 是什么的任何参考资料吗? - Cheok Yan Cheng
我很难找到比我的记忆或旧的线程(如http://www.codeguru.com/forum/archive/index.php/t-236067.html)更好的参考资料。 - Georg Fritzsche
1
这个 bug 在这个 SO 问题中也有一些讨论:https://dev59.com/2EvSa4cB1Zd3GeqPfIma - Michael Burr
谢谢。我将只使用 _MSC_VER 预处理器来绕过它。 - Cheok Yan Cheng

4
fun()函数中,你创建了一个独立的对象aa,然后通过赋值运算符将由a::instance()返回的对象引用的值复制到它上面。但这不会起作用,因为构造函数和析构函数都是私有的。aa应该是一个引用。
a &aa = a::instance();

实际上它尝试通过复制构造函数进行复制。 - Nick Dandoulakis
抱歉,我的代码示例中有一些错误。我已经进行了修正。在VC6中仍然会出现错误,但在VC2008中可以通过。 - Cheok Yan Cheng
1
@Yan:它不会通过,我保证;你的测试是错误的。请给我们你的真实代码而不是示例代码。 - GManNickG
我提供完整的代码(除主函数外)。我测试了很多次。确认VC2008可行,但VC6不行。 - Cheok Yan Cheng
你刚刚修改的代码与之前的代码不匹配。你的新代码运行良好,格式良好,并且可以在任何符合标准的编译器上编译。相反,您的旧代码将在所有符合标准的软件中出现错误。话虽如此,Visual Studio 6.0 不符合标准,这是一个错误。我会添加一个答案。编辑:gf打败了我。:P - GManNickG

2

当fun()函数执行结束时,你的变量将超出其作用域并调用析构函数。

看起来你正在尝试实现一个单例模式 - 也许你的意思是这个?

a& aa = a::instance();

如果aa是一个引用而不是一个实例,那么在fun()函数结束时析构函数不会被调用。


抱歉,我的代码示例中有一些错误。我已经进行了修正。该代码在VC6中仍会出现错误,但在VC2008中通过。 - Cheok Yan Cheng

0

这只是VC6的一个bug。VC6非常容易出错。你可以使用std::auto_ptr<>作为一种解决方法。

#include <memory>

class X
{
    friend std::auto_ptr<X>;
public:
    static X& instance()
    {
        static std::auto_ptr<X> database(new X);
        return *database;
    }
.....
};

请将instance()的实现移至cpp文件中。很抱歉,我不记得确切情况了,但在头文件中实现单例模式时,VC6存在另一个bug。几年前我们使用VC6时曾遇到过几次崩溃。解决方法是将instance()的实现移至cpp文件中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接