5

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'

Cheok Yan Cheng
  • 47,586
  • 132
  • 466
  • 875
  • Should not the constructors/destructors always be public? – vpram86 Feb 26 '10 at 05:57
  • 3
    @Aviator: Constructors shouldn't always be public. Examples: For an abstract class, you only want derived classes calling the constructor (that's how you can prevent instantiation of the abstract class), so you make it `protected`. For singletons you want only the class's static `CreateInstance()` method to create an instance, so you make the constructor `private`. – Scott Smith Feb 26 '10 at 06:01
  • 2
    This code gives error on VC9 also. I can't believe it compiles on any compiler. – Naveen Feb 26 '10 at 06:11
  • This does *not* compile in any compiler. – GManNickG Feb 26 '10 at 06:26
  • Naveen : I do not have VC9. What error you get? Have you tested in VC2008? – Cheok Yan Cheng Feb 26 '10 at 06:50
  • I don't expect things to work correctly on a compiler that doesn't follow the standard –  Feb 26 '10 at 06:51
  • 1
    VC2008 is VC9. There's VC6 == VC98, VC7 == VC2002, VC7.1 == VC2003, VC8 = VC2005, VC9 == VC2008, VC10 = VC2010. – GManNickG Feb 26 '10 at 06:53
  • Also, this is why it's important to give real, working and compilable examples of the code in question, rather than other variations of it. Otherwise we aren't working on the same problem. :) – GManNickG Feb 26 '10 at 06:57

4 Answers4

7

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

Georg Fritzsche
  • 97,545
  • 26
  • 194
  • 236
4

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
  • 11,287
  • 1
  • 28
  • 22
  • actually it tries to copy it via the copy ctor. – Nick Dandoulakis Feb 26 '10 at 06:15
  • Sorry. Some mistake in my code example. I had revised. The code still give error in VC6 but pass in VC2008. – Cheok Yan Cheng Feb 26 '10 at 06:22
  • 1
    @Yan: It doesn't pass, I promise; your test is wrong. Give us your real code instead of example code. – GManNickG Feb 26 '10 at 06:26
  • I provide a complete code (additional of main function). I test it many times. Confirm VC2008 works, but VC6 doesn't. – Cheok Yan Cheng Feb 26 '10 at 06:43
  • 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 – GManNickG Feb 26 '10 at 06:56
2

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().

andrewffff
  • 579
  • 2
  • 6
0

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
  • 631
  • 2
  • 7
  • 9