tags:

views:

205

answers:

4

The following code works fine for Visual C++ 2008. However, when comes to Visual C++ 6, I get the following error. May I know why, and how I can fix the error, but still make the destructor remains in private.

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' : cannot access private member declared in class 'X' C:\Projects\ttt6\main.cpp(175) : see declaration of 'X::~X'

+4  A: 

In fun() you are creating a separate object, aa and then copying the value of the object reference returned by a::instance() to it via the assignment operator. This won't work because both constructor and destructor are private. aa should be a reference:

a &aa = a::instance();
Aaron Klotz
actually it tries to copy it via the copy ctor.
Nick D
Sorry. Some mistake in my code example. I had revised. The code still give error in VC6 but pass in VC2008.
Yan Cheng CHEOK
@Yan: It doesn't pass, I promise; your test is wrong. Give us your real code instead of example code.
GMan
I provide a complete code (additional of main function). I test it many times. Confirm VC2008 works, but VC6 doesn't.
Yan Cheng CHEOK
The code you just changed to does *not* match the code you previously had. Your new code works fine, and is well-formed and will compile on any standards compliant compiler. Contrarily, your old code would have errors in all standards-compliant software. *That said*, Visual Studio 6.0 is *not* standards compliant, and this is a bug. I will add an answer. EDIT: gf beat me. :P
GMan
+2  A: 

When the end of fun() is reached, your variable will go out of scope and the destructor will be called.

It looks like you're trying to implement a singleton - perhaps you mean this?

a& aa = a::instance();

If aa is a reference rather than an instance then the destructor won't be called at the end of fun().

Andrew
Sorry. Some mistake in my code example. I had revised. The code still give error in VC6 but pass in VC2008.
Yan Cheng CHEOK
+7  A: 

The revised sample shows a confirmed compiler bug for VC6 - the common workaround was to simply make the destructor public.

Georg Fritzsche
Do you have any reference for what this bug is?
Yan Cheng CHEOK
I have a hard time finding better references then my memory or older threads like http://www.codeguru.com/forum/archive/index.php/t-236067.html
Georg Fritzsche
This bug was also discussed a bit in this SO question: http://stackoverflow.com/questions/2130864/cannot-access-private-member-in-singleton-class-destructor
Michael Burr
thanks. i will then just use _MSC_VER preprocessor to bypass it.
Yan Cheng CHEOK
A: 

It is just VC6 bug. VC6 is very buggy. You may use std::auto_ptr<> as a workaround.

#include <memory>

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

And, please, move instance() implementation to cpp file. Sorry, I don't remember exact case, but there is yet another VC6 bug with singleton implementation in header files. We had a couple of crashes several years ago when used VC6. The fix was to move instance() implmenetation to cpp.

stas