Polymorphism - what’s allowed..?

Ok, so I am in the process of making a doubly-linked list type thing that has some weird stuff going on with the individual nodes. Basically I have my front and back pointers are of type basic_node* where basic_node is a parent class to a template class node. This is supposed to make it so the list can hold several different types, but I don’t know if it will. All that probably wasn’t very helpful in explaining my problem, but yeah.

Anyways.

Here’s the problem. The only difference between base_node and node is that node has one extra piece of data called data(so creative aren’t I). The thing is I am unsure whether I can access that from a node_base pointer??
I don’t know. 🤷‍♂️ Here’s an example.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
struct node_base {
  node_base *prev, *nxt;
};

template <class T>
struct node : public node_base {
  T data;
};

// ...

int main(){
  node_base* x;
  x = new node<int>;
  std::cout << x->data; // uh........ idk if that’s even allowed it’s not an inherited thingy. 
}


I just never actually looked at polymorphism/inheritance, which is real bad for me right now lol.
To make your life easier you should ideally hold your data in the node struct itself, along with previous and next pointers. Additionally, your class should only perform linked list operations such as insert, delete, etc.

I think what you want is something like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
template<typename T>
struct node {
    T data;
    node<T> *prev;
    node<T> *next;
};

template<typename U>
class NodeClass {
    private:
    node<U> *head;
    node<U> *tail;

    public:
    //your base linked list operations here
};


As a part of your class that performs base linked list operations when you create a new node instance of type int, float, string, whatever you choose. That is when you will use the syntax to create a new instance of a node of type T:
 
node<T>* temp = new node<T>;


I hope this helps some.
Last edited on
Uh. But then it can’t point to a node of a different type. The basic point of it is that node<T1> can be linked to node<T2>, no problem. With that code, it will most definitely throw error, because the pointer will point only to type node<T1> or <T2>. It’s not a normal linked list. 🤷‍♂️
Example
node_base* -> node<int> -> node<std::string> -> node<std::fstream>
The code I provided will work with one data type or several data types. You'll have to specify the type before you call your add_node procedure.

Should be something like:

1
2
3
4
5
6
NodeClass DL_List;

//add an integer
DL_List.add_node<int>(8);
DL_List.add_node<std::string>("Hello");
DL_List.add_node<float>(8.445);


Meanwhile in your class:
1
2
3
4
5
6
7
8
9
10
11
12
class NodeClass {
    private:
    //info

    public:
    template<typename T>
    void add_node(T info){
        node<T>* temp = new node<T>;
        temp->data = info;
        //etc
    }
};


See changed above.
Last edited on
Working with different types can get a little tricky for sure. I suggest trying out some different solutions and seeing what works best for you. There are many ways to solve the same problem, just have to figure out what works best for you. Just trying to point you in the right direction.

If templates can be avoided, another brute force method of achieving your goal is, if you know in advance which data types you'll have, define structs, one for each data type that you'll have. That will require upkeep for more data types, but could work.
Last edited on
You can always use dynamic_cast<...>(...):
1
2
3
4
5
int main(){
  node_base* x;
  x = new node<int>;
  std::cout << dynamic_cast<node<int> *>(x)->data; // Now it's allowed to access 'data'. Note that nullptr will be returned if it is not the expected type
}
> The code I provided will work with one data type or several data types
no, it doesn't
1
2
3
4
5
6
template<typename T>
struct node {
    T data;
    node<T> *prev;
    node<T> *next;
};
a node<T> may only point (be linked to) another node<T>
you can't mix types

also, NodeClass is a terrible name for a linked list.


> This is supposed to make it so the list can hold several different types
¿how do you expect to use it? ¿how do you know the type to cast to?
@x
1: I think you’re still misunderstanding what these structs are supposed to do for me. I don’t want to only be able to handle a single type in a single instance of my list, I want to be able to handle ALL types in a single instance of my list.
@c
I’m not supposed to know what type it is, but maybe.. maybe. Idk, but maybe.
@n
I’m not supposed to know what type it is the problem though. Ideally I’d just get data like nodeN->data and just do whatever operations directly on that.


@everyone, after a few tests and some more thinking, I've found that the OP’s original code is in fact not legal. I am now looking at a new solution using virtual get() and set() functions... I’ll probably post later once I’ve done some more tests..
Nope. Doesn’t work. :( I guess I’ll just have to drop it.
List a few types that you realistically want to store in the list. Try to give some background information.

The relationship between those types might suggest the right way to approach the problem.
Last edited on
There was no problem to be solved with this list thing, it was just a thing that would have been cool. I’ll keep that in mind though..
Have you investigated std::any?
... I mean, no, but Idk what you mean. Maybe I’ll look at it. Yeah I think I can look at it. Thank you! I had forgotten that had existed :)
Topic archived. No new replies allowed.