0

How can I improve the structure of the code below?

I have a nested class. I want to access the parent class which is available as a global vector. The ugly part is when I store the index of the parent class in the child class. Can I do better?

vector<A> vec;

struct A
{
    int val;
    struct B
    {
        size_t id; // Index of the parent in the global vector. Doesn't look good!
        void func()
        {
            cout << vec[id].val;
        }
    };
    B b;
};

int main()
{
    A a;
    a.b.id = vec.size() - 1; // Also ugly!
    vec.push_back(a);
}
Julk
  • 11
  • 2
  • If `B` is only ever used as a member of `A` I would just use a reference. – super Mar 02 '21 at 18:23
  • @super reference where and to what? Reference to a vector member causes error because of the vector resizing which increases it's size in the heap memory space. – Julk Mar 02 '21 at 18:25
  • `a.b.id = vec.size() - 1; // Also ugly!` and probably wrong. Consider the empty case where `size()` is zero. – user4581301 Mar 02 '21 at 19:13
  • @user4581301 good point. but it was for demonstration purpose. not the main problem. – Julk Mar 02 '21 at 19:16
  • Try to get rid of the global vector completely. Why does it exist? – Ted Lyngmo Mar 02 '21 at 19:17
  • @TedLyngmo I need it in my main code. – Julk Mar 02 '21 at 19:19
  • @Julk Sure, but that's connected to the fact that you have a global vector. Not the relationship between A and B. Is seems better to make it work no matter where and how A is used, which it would if you use a reference and implement proper copy and move constructors/assignements. – super Mar 02 '21 at 19:20
  • 2
    You rarely need global variables. If we knew more about the classes it'd be easier to suggest improvements. – Ted Lyngmo Mar 02 '21 at 19:22
  • @super I don't know how to do it. Can you give me an example on how to create the proper move and copy constructors/assignments? – Julk Mar 02 '21 at 19:24
  • @TedLyngmo I need to define it as a global variable because I need to use it in multiple functions/cpp file. – Julk Mar 02 '21 at 19:29
  • @Julk It sounds like those functions have something in common. Perhaps they should be class member functions and the vector a class member variable? – Ted Lyngmo Mar 02 '21 at 19:31
  • @TedLyngmo I could perhaps do that. It would make little difference. The problem still stands. – Julk Mar 02 '21 at 19:41
  • As I said, if we knew more about these classes it'd be easier to come up with suggestions about how to improve it. You now have a problem that may not even need to exist. – Ted Lyngmo Mar 02 '21 at 19:44

2 Answers2

1

Firstly you should not make use of global variables at all. It is quite bad practice, as any variable lacking access specification can be altered at any point by the program.

This is not so much of an issue with a small program such as this, but in bigger projects you might end up with some very nasty bugs if you were to continue using global variables.

Next, it makes sense to redefine this struct. There is no explicit rule, but in my opinion a struct should not really contain anything other than data members. It would instead be better to define a class, perhaps containing a struct similar to struct b if that is what you wanted. Personally however that is not how I would approach this problem.

Consider instead defining a class A, you might have a variable for "value". Then you might define a function that is passed a value that you want to assign that assigns a value to the "value" variable of that class.

Then within main you might instantiate a vector of "A"s, then set up a for loop(or some other kind of loop it is your choice after all). That for loop can then iterate however many times you tell it to. Per iteration you could instantiate an "A" object, initialise the value within the object, and then push the object onto the back of the vector of "A"s.

At any point within the scope of the main function you can iterate by another for loop through the vector of "A"s to access by index the the "A" object that is required, through which the value can also be accessed. So long as your for loop is set up to begin iterating from a count of 0, the index value for each element of the vector of "A"s will be the same as the the for loop's control variable at each iteration.

The approach that has been outlined is not the optimal solution, however as with all programming there are a number of solutions to your problem and it is up to you to find which is best. Given the context provided it makes sense not to confuse you further by overloading you with information but there are many ways to improve the potential solution outlined above.

Hopefully this answer shows you another path to the same destination, that perhaps is a little bit cleaner and more manageable. Furthermore as a first time responder I hope I have not made any mistakes myself(please let me know if I messed anything up here other readers)! Good luck with your programming!

helpful_IO
  • 11
  • 1
0

I think you will need to pass a pointer of the enclosing class to the nested class to be able to use the enclosed class's non-static members.

See the PIMPL idiom for example here: Why would one use nested classes in C++?

Could write classes like this:

#include <iostream>
#include <memory>

struct A
{
    int val;
    int getv() {return val;}
    struct B
    {
        A * my_parent;
        B(A * a) : my_parent(a) {}
        void func()
        {
            std::cout << my_parent->val << std::endl;
        }
    };
    std::unique_ptr<B> b;
    A();
};

A::A() : b(new B(this)) {}

int main()
{
    A a;
    a.val = 1;
    a.b->func();
}
GandhiGandhi
  • 1,029
  • 6
  • 10
  • I don't think this would work. Because I'm using A in a vector; which uses the heap memory space and does resizes (which changes references). – Julk Mar 02 '21 at 19:48