Public Group

# Console Menu Structure - How to get node type

## Recommended Posts

I tried to edit the post, but the editing option expired. So here's the new version.

Spoiler


{
int type_ID{0};
public:
int getType_ID();

};


#include <vector>

{
int fixed_set{0};
int current_index{o};
public:

{
}

{
}
};



{
setType();
}



{
public:

{
action_call=1,
root=2,
//...
}

//possible applications:

{
//finds the first of a type

{
{
return iterator;
}
}

return 0;
}

{
//finds all of the same type, stops after finding 5th menu item

int results{0};

for(int iterator{1};(iterator<=loop_box.getSubMenuSize() && iterator <= 5);iterator+=1)
{
results+=1;
}

return results;
}
};

main.cpp


#include <iostream>

std::string getNodeType(int type_wanted)
{
{
return "root";
}

{
return "action call";
}
}

int main()
{

//possible use:

//the 1 here means action call
int first_index{ E.loop_findFirstType(D, 1)};

//here it means finding the node type
//this should return 1(searching index result) as MenuItem

//after indefying the first MenuItem of action call type index,

std::cout << getNodeType(D.getAdress(1)->getType());

##### Share on other sites

I probably just programmed the manual dynamic_cast version in the most cumbersome way possible but at least its a starting point for my brain to work with. Thanks anyway Acosix and of course all the others who helped me.

(Not tested, no production code!)

class MenuItem {
private:
size_t typeID;
std::string name;
static size_t generateID() { static size_t id; return id++; }
public:

template <typename T>
static size_t getTypeID() {
static size_t id = generateID();
return id;
}

void setName(const std::string& n) { name = n; }
const std::string& getName() const { return name; }

void setID(size_t id) { typeID = id; }
size_t getID() { return typeID; }
};
class ActionItem : public MenuItem {
public:
ActionItem(const std::string& displayName) {
setName(displayName);
}
};
class SubmenuItem : public MenuItem {

private:

for (auto& child : childs)
{
if (child->getName() == name)
return child;

{
if (sub->childItems.size() <= 0)
return nullptr;
else
return findRec(name, sub->childItems);
}
}
return nullptr;
}
public:
setName(displayName);
}

template <typename T>
T* get(const std::string& whatIwant)
{

if (temp && temp->getID() == MenuItem::getTypeID<T>())
return static_cast<T*>(temp);
else
return nullptr;
}

{
childItems.push_back(item);
}

//Only for testing
void print() {
cout << "=====================================" << endl;
cout << "childItems from -- " << getName() << " -- " << endl;
cout << "=====================================" << endl;
for (const auto& m : childItems)
{
cout << m->getName() << endl;
}
cout << "=====================================" << endl;
}
};

##### Share on other sites
Posted (edited)

Top code, man. But do you have any questions regarding it; or any other which could've arose by newest posts?

Edited by Acosix

##### Share on other sites
Posted (edited)
class SubmenuItem : public MenuItem {

private:

//...

Why do you have a pointer to the base class?

This can soon lead to recursivity errors.

This would work:

class A
{
int Ac;
};

class B
{
A* a;
};

This would throw recursive errors however.

class A
{
B b1;
};

class B
{
A* a1;
};

You can't have two classes point at each other, even if they
are defined in separate header files. Recursive code is
error-prone as it in this case means you make define the
same class twice.

Also you use the #include file pre-processor command,
which means there are multiple of header compiled
definitions, leading to even more errors.

A.h

#pragma once

#include "B.h"

class A
{
B b1;
};

B.h

#pragma once

#include "A.h"

class B
{
A* a1;
};

#pragma once is a command for linker and compiler not to
define the same header multiple times. Recursive definitions
bypass this command.

are two separate classes.

I'm not showing you this as how to code in C++, I'm just
saying once you get into above problem, you'll run
into a very large amount of errors. Even though you know
now ( or you have learnt before ), this can lead to
very hard to fix errors.

Like I've mentioned before, SubmenuItem Is a container for
the MenuItem instantiations. I showed how to do this in
my last previous post.

Polymorphism is an extension of inheritance. It uses
the definition of inheritance as "is-a".

A derived class is-a of base class, for example:
you have a base class Fruit and a derived class Apple.
An apple is a fruit.

Quote

is a container for the abstract MenuItem instantiations.

Edited by Acosix

##### Share on other sites
27 minutes ago, Acosix said:

Why do you have a pointer to the base class?

This can soon lead to recursivity errors.

You can check out the composite pattern. Because MenuItem is the base class I have to use a pointer to the base class in order to store any "MenuItem" in it....

28 minutes ago, Acosix said:

You can't have two classes point at each other, even if they
are defined in separate header ﻿files

Sure you can  forward declare your class and use a pointer.

class B;
class A {
public:
B* b;
}

class B {
public:
A* a;
}

36 minutes ago, Acosix said:

is a container for the abstract MenuItem instantiations.

Therefore it would (in my case) be pointless to not inherit from MenuItem. Especially with the type system in place.

##### Share on other sites
Posted (edited)
48 minutes ago, Acosix said:

You can't have two classes point at each other, even if they
are defined in separate header files.

This is plain wrong.

The keyword here is forward declaration:

class B;

class A
{
public:
B* mB;
};

class B
{
public:
A* mA;
};

int main(int, char**)
{
A myA;
B myB;

myA.mB = &myB;
myB.mA = &myA;
}

Compiles just fine. A pointer is just an address and does not need any information about a class, apart from that it exists. Problems with ring dependencies start when it comes to dynamic memory allocation and ownership issues, but there are special smart pointers for that in the STL: shared_ptr & weak_ptr.

As far as I know, a lot of GUI libraries use such mechanisms under the hood to traverse the dependency trees.

Greetings

EDIT: ninja'd by @Geosesarma 😛

Edited by DerTroll

##### Share on other sites

I won't argue with you. It would just go off-topic. I could explain why forward declaration is bad in my opinion, but trying to convince others I could be right has always got me into flaming discussions.

##### Share on other sites
5 minutes ago, Acosix said:

... I could explain why forward declaration is bad in my opinion ...

I have no problem with the "contract" principle, in this case the contract to provide an implementation when i feel it's time to do so. As long as the compiler fulfils its part ;-)

C++ lets you use it the way you want, without knocking on your fingers every time you do something that might need sort of a supervision. More freedom. Other languages fit tighter. All have their purpose.

##### Share on other sites
18 minutes ago, Green_Baron said:

I have no problem with the "contract" principle, in this case the contract to provide an implementation when i feel it's time to do so. As long as the compiler fulfils its part 😉

C++ lets you use it the way you want, without knocking on your fingers every time you do something that might need sort of a supervision. More freedom. Other languages fit tighter. All have their purpose.

Thanks for clarification matey - what regards the flexibility of C++.

I have been  trying to say, the forward declaration is off-topic. You mention to the OP they should consider forward declaration. If they like it or want to use, it's their way - regardless this is a Beginner's Public Group.

Quote

Console Menu Structure - How to get node type

This is the name of the topic, not forward declaration.

##### Share on other sites
53 minutes ago, Acosix said:

I have been  trying to say, the forward declaration is off-topic. You mention to the OP they should consider forward declaration. If they like it or want to use, it's their way - regardless this is a Beginner's Public Group.

1

I don't think it's off-topic if it is part of a potential solution (as it seems to be). You said, two classes pointing at each other is not possible, which is not true.

@Geosesarma and I provided code that showed the opposite. As I said before, to my knowledge child and parent keeping pointers to each other is a common pattern in GUI libraries.

As @Green_Baron stated, C++ let you do things in many different ways. That's its big strength and also its biggest flaw since it doesn't stop you from programming yourself into a corner. If you just wanted to say, that the pointer approach can get you into trouble then you are right. But as long as you know its problems (and also how to handle them) and have a good reason to use it (I think he does), it is a valid solution.

Greetings

• 18
• 18
• 11
• 21
• 16