Pointer to an array of pointers to a structure

Hi,
I have an abstract class like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Obj
{
    public:
       virtual int someFunc()=0;
    protected:
        struct A
        {
            int Index;
            std::string Name;
            std::string Hier;
        };
        A **a;
};


And then I derive a class from this like this:
1
2
3
4
5
6
7
8
9
class derObj : public Obj
{
    public:
        int someFunc();
    private:
        struct A a[2] = {
          { 1, "name","Top" }, { NULL, NULL, NULL}
        }
};


This doesn't work out however and I get error messages:

1
2
3
4
error: a brace-enclosed initializer is not allowed here before '{' token
error: ISO C++ forbids initialization of member 'a'
error: making 'a' static|
error: invalid in-class initialization of static data member of non-integral type 'Obj::A [2]'


Please can anybody help me determine what is causing this error. Any help would be appreciated. Thanks.


You cannot initialise arrays in the class declaration like that
Thanks for the reply. So how should I initialize this array? Do I need to initialize this in the constructor? I need this to be a const array that needs to be initialized in the derived class but it needs to be accessible from the function defined in the parent class.
After I shift the array initialization to the derived object constructor:

1
2
3
4
5
6
derObj::derObj()
{
        struct A a[2] = {
          { 1, "name","Top" }, { NULL, NULL, NULL}
        };
}


I get the following warning:

 
warning: unused variable 'a'


pointing to the initialization line.
Last edited on
You are defining local variable with automatic storage duration inside derObj. It simply hides the member field from the parent class, it doesn't assign to it. In your example, the data assigned in the constructor is always the same, but I assume it wont be in practice. Here is example of what you could do:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Obj
{
protected:
  struct A
  {
    int Index;
    std::string Name;
    std::string Hier;
  };

  explicit Obj(int size) : a_(new A[size]) {}
  ~Obj() { delete[] a_; }

  A *a_;
};

class derObj : public Obj
{
public:
  derObj() : Obj(2)
  {
    a_[0] = (A){ 1, "name","Top"  };
    a_[1] = (A){ 0, NULL, NULL };
  }
};

Regards

1
2
3
4
5
6
7
8
derObj::derObj()
{
   //This variable a  is local to the constructor and  is not the a declared in the private section
//of the derived class     
 struct A a[2] = {
          { 1, "name","Top" }, { NULL, NULL, NULL}
        };
}


warning: unused variable 'a' - this type of message is means that you have decared a variable in a function but you haven't used it.


The initialisation of inclass arrays is always an issue.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
class Obj
{
    public:
       virtual int someFunc()=0;
    protected:
        struct A
        {
            int Index;
            std::string Name;
            std::string Hier;
        };
        A **a;
        
};

class derObj : public Obj
{
    public:
    derObj();
        int someFunc();
    private:
        struct A a[2] ;
};

derObj::derObj()
{
    a[0].Index = 1;
    a[0].Name =   "name";   
    a[0].Hier =  "Top";   
    
    a[1].Index =0;
    //a[1].Name and a[1].Hier are std::strings and are already default constructed.

}

int derObj::someFunc()
{
    //To be completed
    return 0;
    
}

Hi simeonz,
The data assigned to the array will always be the same. It can be a const array. Also what does this line do?

 
explicit Obj(int size) : a_(new A[size]) {}


I don't understand how this code works.

Thanks guestgulken for your solution. Would this initialization be available from Obj member functions? Also is there a easy way to initialize the array rather than a statement by statement initialization?
aryajur wrote:
The data assigned to the array will always be the same. It can be a const array.
Then you can try this instead:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Obj
{
protected:
  struct A
  {
    int Index;
    std::string Name;
    std::string Hier;
  };

  explicit Obj(const A a[]) : a_(a) {}

  const A *a_;
};

class derObj : public Obj
{
  static const A a_init_[];

public:
  derObj() : Obj(a_init_)
  {
  }
};

const Obj::A derObj::a_init_[] = {
  { 1, "name","Top"  },
  { 0, NULL, NULL }
};

aryajur wrote:
Also what does this line do?
The line you quoted initializes a_ with the pointer to dynamically allocated array of A objects. The dynamic allocation is performed with the "new" operator, and the syntax following the colon is called member initializer list, and allows you to construct sub-objects like a_. There is no other way to explicitly construct sub-objects, but using this syntax. You can always assign the members inside the body of the constructor after they have been already default constructed, but member initializer lists allow you to use parametrized constructors. Arguably, it doesn't matter in this particular case. I could've assigned the a_ pointer inside the constructor with the same effect.

Regards
Thanks for explaining this in detail.
One last question is if I want a default initialization of a_ in Obj how do I add that?
Last edited on
I don't understand. If you initialize the a_ field to point to the a_init_ array, as I did in my previous post, it shouldn't be a problem. The snippet that you show above is for setting the value of a_init_. You can set a_ to point to a_init_, but still, a_ is only the pointer. It does not store data, it only points to the data that you could define as array somewhere.
The above solution you gave works very nicely. I only had to change the string initialization from NULL to "" otherwise it was crashing.

The only thing remaining is how do I define a default structure and assign it to a_ in case a derived class does not provide something.
You could do this then:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Obj
{
protected:
  struct A
  {
    int Index;
    std::string Name;
    std::string Hier;
  };

private:
  static const A a_default_init_[];

protected:
  explicit Obj(const A a[] = a_default_init_) : a_(a) {}

  const A *a_;
};

const Obj::A Obj::a_default_init_[] = {
  { 1, "name", "Top"  },
  { 0, "", "" }
};
Now, whenever no argument is supplied to the Obj constructor, it a_ will be pointed to a_default_init_.

Regards
Topic archived. No new replies allowed.