2

I need some guidance. I am trying to build a class B2 that has among its members an object from class A2. Class A2 on the other hand allocate some memory through the member pointer '*y' in a dynamical fashion. Here is my code that right now does not compile.

#include <stdio.h>
#include <stdlib.h>
#include <iostream>

class A2{
int N;
public:
    double *y;
    A2(int N_);
    ~A2(){free(y);};
};

A2::A2(int N_){
    N = N_;
    y = (double*)calloc(N,sizeof(double));
}

class B2{
    int N;
    public:
        A2 obj(N);
        B2(int N_) : N(N_) {};
        ~B2(){};
};

int main(){
     int N = 10;
     B2 model(N);
     for(int i=0;i<N;i++) model.obj.y[i] = i;
     for(i=0;i<N;i++) printf("\ny[%d]=%d",i,model.obj.y[i]);
     return 1;
}

When I try to initialize model I get the error: ‘N’ is not a type in the initialization of A2 obj(N) this is why I thought to use a member initializer list as suggsted by this post.

maurizio
  • 745
  • 1
  • 7
  • 25
  • In your class B2, what's A2 obj(N); supposed to mean? int N maybe? Also, I'd suggest you stay consistent with respect to variable names (uppercase vs lowercase). It's really confusing at it is right now. – AlexG Jun 21 '18 at 16:57
  • Hi @AlexG `A2 obj(N)` means that `B2` contains an object of class `A2` whose member pointer `*y` points to a cluster of `N` double on the heap... – maurizio Jun 21 '18 at 16:59

3 Answers3

2

You cannot use N in the member declaration; use initializer list instead.

Here is how to fix your B2 definition:

class B2{
    int N;
    public:
        A2 obj;
        B2(int N_) : N(N_), obj(N_) {};
        ~B2(){};
};

Above, obj(N_) supplies N_ to obj's constructor while constructing B2.

Demo.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • I see. Precisely what I needed to figure out on how to initialize class members that requires some initialization. Then there is one further issue. My assignment to `y` in the main does not mirror what I want... – maurizio Jun 21 '18 at 17:02
  • @maurizio That's because you aren't printing them correctly. Use `%f` in place of `%d`, See my fix in the demo. – Sergey Kalinichenko Jun 21 '18 at 17:14
  • Yeah thanks I figured that out. I was looking into my example actually. In practice my class is much more complicated and I have to do some lengthy operations within the initializer. In all the [examples](http://en.cppreference.com/w/cpp/language/initializer_list) that I see it is always something like `class() : ... {};`. What about if I want to include some lengthy code in between `{}`. How can I do it separately from class declaration, using `class::class... {}`? Is this even allowed? – maurizio Jun 21 '18 at 17:19
  • @maurizio Including lengthy code in between `{}` is absolutely not a problem - in fact, that is what the `{}` are for. Initializer list syntax works fine even outside the header, so `B2::B2(int N_) : N(N_), obj(N_) { /* lengthy code */ }` works as well. – Sergey Kalinichenko Jun 21 '18 at 17:30
  • It look like the only solution is to delegate other operations to a separate member function and call then that function within the compound statement upon initialization, suggested in [this post][https://stackoverflow.com/questions/27299344/doing-necessary-work-before-member-initialization-in-constructor]. If any other option is available, let me know. I don't know if this should be posted as a separate question as it might be of some interest. – maurizio Jun 21 '18 at 17:30
  • Yeah, I just find it "ugly" to include lenghty code inside the class declaration. I'd rather have declaration and definitions as much as possible separated for clarity... – maurizio Jun 21 '18 at 17:32
  • Actually a minor correction on my post above. The right suggestion to include complicated stuff in the brackets is shown [here](https://stackoverflow.com/questions/1014518/right-way-to-conditionally-initialize-a-c-member-variable). – maurizio Jun 21 '18 at 17:52
1
A2 obj(N);
B2(int N_) : N(N_) {};

should be

A2 obj;
B2(int N_) : obj(N_) {};
f4.
  • 3,814
  • 1
  • 23
  • 30
1

If you are using c++11, You can use {} initializer for initialization of member (in case it is not supplied in constructor member initializer list).

class B2{
    int N;
    public:
        A2 obj{N};  // <<<=== change () to {}
        B2(int N_) : N(N_) {};
        ~B2(){};
};

Relevant section of cppreference.com is

2) Through a default member initializer, which is simply a brace or equals initializer included in the member declaration, which is used if the member is omitted in the member initializer list

If a member has a default member initializer and also appears in the member initialization list in a constructor, the default member initializer is ignored.

Please note that you can use brace or equal (not parenthesis). That is reason your code fails in compilation. Also note that member initializations happen in declaration order.

code707
  • 1,663
  • 1
  • 8
  • 20
  • Thanks for the clarification. I saw indeed this notation somewhere else but I could not clarify its use. Now it is clear. Awesome thanks. – maurizio Jun 25 '18 at 09:26