0

Here is my header code:

#ifndef CLANDTYPES_H
#define CLANDTYPES_H

class CLandTypes
{
public:
    CLandTypes();
    ~CLandTypes();
private:
    class Pimple;
    static Pimple * d;
};

#endif // CLANDTYPES_H

because it should be a static class I tryed to code in my cpp file:

#include "clandtypes.h"

CLandTypes::Pimple * CLandTypes::d = new CLandTypes::Pimple();
...

But something is wrong!

---------- EDIT ----------

here is my extended c++ code:

#include "clandtypes.h"

#include "qvector.h"
#include "qpair.h"

CLandTypes::Pimple * CLandTypes::d = new CLandTypes::Pimple();

class CLandTypes::Pimple
{
public:
    Pimple();
    ~Pimple();

    QVector > LandTypes;
};

CLandTypes::Pimple::Pimple()
    : LandTypes(NULL)
{
    LandTypes.push_back(qMakePair((unsigned int) 0, (QString)"undefined"));
    LandTypes.push_back(qMakePair((unsigned int) 1, (QString)"rocky"));
}

CLandTypes::Pimple::~Pimple(){}

CLandTypes::CLandTypes()
{
    if (!d)
    {
       d = new Pimple();
       if (!d)
       {
           throw std::bad_alloc();
       }
    }
}

CLandTypes::~CLandTypes()
{
    if(d)
    {
        delete d;
        d = NULL;
    }
}

my two errors are:

invalid use of incomplete type 'struct CLandTypes::Pimple'
forward declaration of 'struct CLandTypes::Pimple'

oRUMOo
  • 153
  • 1
  • 2
  • 11

2 Answers2

1

Move this line:

CLandTypes::Pimple * CLandTypes::d = new CLandTypes::Pimple();

to be after the class definition for CLandTypes::Pimple.

It's objecting to your attempt to use new to create an instance of a class it knows nothing about.

If you do this, remove the code that checks to see if d is nullptr (aka !d) in your definition of the CLandTypes::CLandTypes constructor. This code can result in a memory leak. Also, checking again after you've called new and then throwing ::std::bad_alloc is totally unnecessary as new is defined to throw ::std::bad_alloc on an allocation failure.

The way the memory leak can occur is if the constructor is run before the static initializer that initializes CLandTypes::d is run. And that can only happen if the constructor for CLandTypes is used in a static initializer someplace else. What will happen is that the constructor will give a value to d and then the static initializer for d will run sometime later and overwrite that value, thereby causing a memory leak.

Omnifarious
  • 54,333
  • 19
  • 131
  • 194
  • Yes - shall I somthing do? (I don't know the platform very well) – oRUMOo Apr 25 '11 at 18:56
  • @oRUMOo: There should be a little check box right underneath the vote count (the place where there are an up and down arrow with a '1' between them). Check it, and that marks my answer as 'accepted'. – Omnifarious Apr 25 '11 at 21:04
0

Try declaring "class Pimple" as public rather than private and try and let me know if that helps. Make sure you define the class before instantiating it.

aeon
  • 1,029
  • 2
  • 13
  • 23
  • to public the class Pimple is not a good idea, because it destroyes the pimple-idiom. – oRUMOo Apr 25 '11 at 10:40
  • @oRUMOo: In theory it does, in practise your users still have to see the name in your header file, so it may as well be public. – quamrana Apr 25 '11 at 11:21
  • @oRUMOo: If you want to access class members outside of your class they have to be public. If you want the members to be private, have accessor type methods to expose it through public wrapper functions. If you want to have a static reference to this Pimple try having a static container class object. – aeon Apr 25 '11 at 14:21