Inheritance complications

Hi!
I'm currently having a quite ugly problem with some classes. To describe the issue, I'd say that:
I have a parent class ("parent"), which contains a structure ("node" - because it is used in a sort of stack mechanics but that's not important right now). This node structure must contain a structure pointer ("link").
I also have a couple of classes deriving from "parent", which we can call "Child1", "Child2", etc. For now I'll only take in consideration one child, to make things simpler.
Now it comes to the hard part: The structure type that "link" (from the base class) points to, should differ from child to child. The problem is: I can't simply leave out the definition of "parent" and separately define it for each child, because there are functions from the base class which actually use "link".

Here's a short code which could make things a bit clearer:
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
#include <iostream>
using namespace std;

struct problem{
    int data;
};
class parent{
    public:
    struct node{
        void *link;
    };
    void remove();
    node* current;
};
void parent::remove(){
     delete current->link;
};
class child:public parent{
    public:
    struct node:parent::node{
    };
    void add();
};
void child::add(){
     node* newNode=new node;
     newNode->link=new problem;
     current=newNode;
};

int main(){
    child test;
    test.add();
    cout<<test.current->link->data;
    test.remove();
    return 0;
};

It compiles with a `void*' is not a pointer-to-object type", which is of course true.
But how can I make it work? (polymorphing the classes wouldn't help too much, as I meet other problems later on).

Thanks!
Just finish a class where i´ve learned about polyphormism and for what you do need to do seems like you need to use polyphormism...
Actually, it sounds like you might want to use templates instead. If child isn't really adding much beside changing the "type" of link, I would make parent a template class.
I thought of templates too, but would it be possible to create a template specialization for the parent class, which adds certain variables to the already defined generic class, as it would work with inheritance (it must not entirely replace the generic content)? What I mean is that the "childs" - in this case specializations - should have a few additional functions and variables.
Last edited on
What if you make a base class, Link, and then derive Child_1_Link, Child_2_Link, etc... from it?

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
struct Link { virtual ~Link() {} };
struct Parent
{
    struct Node {Link * link;};
    Node * current;

    Parent(Link * new_link)
    {
        current=new Node;
        current->link=new_link;
    }

    virtual ~Parent()
    {
        delete current->link;
        delete current;
    }

    //...
};

struct Child_1_Link : public Link {};
struct Child_1 : public Parent
{
    Child_1():Parent(new Child_1_Link) {}

    //...
};

struct Child_2_Link : public Link {};
struct Child_2 : public Parent
{
    Child_2():Parent(new Child_2_Link) {}

    //...
};

It would really help, though, if you told us what these classes (parent and children) represent.

EDIT:

Ramses12 wrote:
polymorphing the classes wouldn't help too much, as I meet other problems later on

I just saw this. What do you mean by polymorphing the classes?
You mean what I suggest here? What are these other problems?
Last edited on
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
43
44
45
46
47
48
49
50
51
#include <iostream>
using namespace std;

struct linkPar{
};
struct problem:public linkPar{
    int data;
};
class parent{
    public:
    struct node{
        node *next;
        linkPar *link;
    };
    void remove();
    node* getCurrent();
    node *first,*last,*current;
};
void parent::remove(){
    node* temp;
    temp=current;
    delete current->link;
    current=current->next;
    delete temp;
};
parent::node* parent::getCurrent(){
    return current;
}
class child:public parent{
    public:
    struct node:parent::node{
        int child1data;
    };
    void add(int);
};
void child::add(int val){
     node* newNode=new node;
     newNode->link=new problem;
     newNode->link->data=val; //linkPar has no member named 'data'
     last=newNode;
     current=newNode;
};

int main(){
    child ch;
    ch.add(21);
    child::node* test;
    test=ch.getCurrent(); //invalid conversion from `parent::node*' to `child::node*'
    ch.remove();
    return 0;
};
(the comments are the errors thrown). And if I replace child::node* with parent::node*, then I can't access test->node->data anymore, because it considers test to be just a linkPar.

It would really help, though, if you told us what these classes (parent and children) represent.
Well, the childs are sections of data that have to be compiled together in a database file. Each section has to be able to hold several "items" of data (different kind of data per section), and thus every section has pretty much the same functions (a list/queue system which implements functions like add(), remove(), getCount(), getFirst(), getLast(), reset(), next(), getCurrent(), clear(), as well as some file-related variables (location and length of data blocks in the file and so on). The only difference between sections is the specificity of the data, and maybe some functions related to optimisation and all sorts of general data management.
You could make getCurrent a virtual function. I believe this should work:

...

Note that if you don't need to work with parent pointers to child instances,
simply overloading the getCurrent function would work.


On second thought, I think it would be better to write code
based on abstractions (parent pointers, parent link pointers, etc...)
and use virtual functions whenever you want child specific behavior.

I mean, you could write your code in a way that you don't have to
make such an assignment -> child::node* test=ch.getCurrent();.

child::nodes should not appear outside the respective child class.
Neither should child classes appear in main, except perhaps from the part where they are
created (which could also be encapsulated inside a factory, thus hidden from client code)

As for the other problem, you could provide (virtual) get/set functions.

Ramses12 wrote:
The only difference between sections is the specificity of the data, and maybe
some functions related to optimisation and all sorts of general data management.

Consider something like this, then, where Data is a class
encapsulating the data specific stuff you mentioned:

1
2
3
4
5
6
7
8
9
class parent {/*...*/};

template <class Data>
class child : public parent
{
    Data data;

    //...
};
Last edited on
I've made it! With just one templated class. As template parameter, I've included a separate structure which contained the neccessary functions and variables.
Thanks for all help!
Topic archived. No new replies allowed.