C++: Cloning and overloading with multiple inheritance - c++

This is a follow-up to this question. Someone asked about a minimal example, but I found it impossible to condense it all into something working. I still have issues, so I hope that by giving a bit more structure I can get some idea of what I am doing wrong or what I should be doing.
The classes I use form a tree structure, like this:
struct Base
{
/* nodeType is a number uniquely assigned to each concrete class */
int nodeType;
int numberOfA;
int numberOfB;
int NumberOfC;
int numberOfD;
AdvancedA** A_array;
AdvancedB** B_array;
AdvancedC** C_array;
Intermediate1** D_array;
virtual Base clone() = 0;
}
struct Intermediate1 : Base
{
}
struct Intermediate2 : Base
{
}
struct Advanced_A : Intermediate1
{
/* There might be different signatures since arguments might be
* real-valued, complex, or even matrices
*/
virtual double compute(signature 1);
virtual double compute(signature 2);
}
struct Advanced_B : Intermediate1
{
virtual std::complex compute(signature 1);
virtual std::complex compute(signature 2);
}
struct Advanced_C : Intermediate2
{
virtual matrix compute(signature 1);
//for example; definition of matrix class is not shown
}
struct Instance_A1 : Advanced_A
{
}
struct Instance_A2 : Advanced_A
{
}
...
struct Instance_B1 : Advanced_B
{
}
...
struct Instance_C1 : Advanced_C
{
}
...
I use these objects to build expression trees, which can evaluate to different types, corresponding to the three Advanced types. (Think of them as real-valued, complex-valued and matrix-valued expressions.) Because I need to evaluate the expressions, I have created three different types of expression trees, as follows.
struct BasicTree
{
virtual void cloneTree();
}
struct TreeType_A : BasicTree
{
Advanced_A* root;
}
struct TreeType_B : BasicTree
{
Advanced_B* root;
}
struct TreeType_C : BasicTree
{
Advanced_C* root;
}
I hope to eventually be able to use these in this manner:
TreeType_A* tree_A;
TreeType_B* tree_B;
TreeType_C* tree_C;
TreeType_A* copy_A;
TreeType_B* copy_B;
TreeType_C* copy_C;
copy_A = tree_A->cloneTree();
copy_B = tree_B->cloneTree();
copy_C = tree_C->cloneTree();
tree_A->root->compute(signature 1);
tree_B->root->compute(signature 1);
tree_C->root->compute(signature 2);
I have two concerns: The cloning of the array of Advanced elements will have to also clone the descendants. At the moment I put his into the method itself:
Base* Instance1::clone()
{
Base* temp = new Instance1();
(clone local stuff)
for (int i = 0; i < numberOfA; i++)
temp->A_array[i] = this->A_array[i]->clone();
for (int i = 0; i < numberOfB; i++)
temp->B_array[i] = this->B_array[i]->clone();
for (int i = 0; i < numberOfA; i++)
temp->C_array[i] = this->C_array[i]->clone();
for (int i = 0; i < numberOfD; i++)
temp->D_array[i] = this->D_array[i]->clone();
return temp;
}
If possible I would actually prefer to write a method cloneChildren that takes care of the recursion transparently.
Mostly I want to avoid having to use explicit casting. Different instances of the Advanced classes have different content, and this content seems to get lost if I try to write, e.g.
temp->A_array[i] = ((Advanced_A*)this->A_array[i])->clone();
On the other hand, using a long case statement based on the particular instance seems inefficient. So it seems I need to rely on automagic.
If further simplifications are possible, such as collapsing everything into a single tree type, or a single array of children, that would be great. (I doubt the former will work, because the compute functions need to look different and return different values for each type of root. The latter seems more promising to me.)
What other pitfalls might there be?

Related

how to declare variables based on other params in C++

I have the below code (eg):
void Foo(int ip_selector)
{
ipv4_hdr_t ipv4;
ipv6_hdr_t ipv6;
{
…
if(ip_selector == 0)
addStack(ipv4);
else
addStack(ipv6);
}
{
…
if(ip_selector == 0)
addStack(ipv4);
else
addStack(ipv6);
}
…
}
int main()
{
for (int i = 0; i < 2; i++) {
Foo(i);
}
}
In the above code, addStack param depends on the selector param in Foo(). The above code works fine, but does to the scale it can grow, I do not want to add if ip_selector check everywhere in Foo() to see which arg to be passed in addStack(). I am trying to find a way to select either ipv4_hdr_t/ipv6_hdr_t without writing an if else condition. Infact, I dont even need the ipv6 declaration of ip_selector is 0 (vice versa for that matter)
here is one way to solve such a problem.
1.have a base class for your protocols, say Protocol.
2.derive your ip4/ip6/whateverelse classes from the base class.
3.create an array of available protocols.
4.use the selector to pick an array element.
class Protocol {
virtual void addStack() = 0;
...
};
class Ip4Protocol : public Protocol {
ip4_hdr_type hdr;
void addStack(){...}
};
vector<Protocol*> availableProtocols = {
new Ip4Protocol(),
new IP6Protocol(),
...
};
...
for (int i = 0; i < availableProtocols.size(); i++) {
avalableProtocols[i]->addStack();
}
or you can probably use templates on the derived classes as well
termplate <class P> class IP : public Protocol {
P hdr;
void addStack() {addGlobalStack(hdr)};
}
ther are tons of other possibilities as well.

How to avoid typeid with better abstraction?

I am using typeid in my code, but it seems to me that the code can be cleaner if I avoid typeid.
If we want to store the type of the class, why would we choose an object-oriented language in the first place?
But I see this pattern over and over again and I do not know how to avoid it.
So I am thinking if this code can be written cleaner with a better abstraction?
Here is the code:
class A {
public:
string type;
};
template <typename T>
class B : public A {
public:
B() {
type = typeid(T).name();
}
};
class Registry {
private:
std::vector<A *> list;
public:
void append(A * a) {
int found = 0;
for (A * el : list) {
if (a->type == el->type) {
found = 1;
break;
}
}
if (!found)
list.push_back(a);
}
int size() {
return list.size();
}
};
int main(int argc, char **argv) {
Registry reg;
A * b_int1 = new B<int>();
A * b_int2 = new B<int>();
A * b_float = new B<float>();
reg.append(b_int1);
reg.append(b_int2);
reg.append(b_float);
cout << reg.size() << endl;
return 0;
}
The output is 2. (which is the expected result)
Basically we do not want to store two object of the same type in a list.
If you don't want visitors, but you'd like a quick RTTI, I'd suggest looking into this paper: http://www.stroustrup.com/fast_dynamic_casting.pdf
The idea is:
Each class is assigned a distinct prime number for it's own type (e.g., A::my_type = 2; B::my_type = 3)
Then each class is additionally assigned the product of its type and base class values if any (e.g., A::can_cast = A::my_type; B::can_cast = B::my_type * A::can_cast; )
This solves the is_same_dynamic(), is_base_dynamic() problems elegantly: former becomes ==, latter becomes %.
To check whether or not an object belongs to a class derived from a given class, one might use the dynamic_cast<T*> and compare the result with nullptr. Unfortunately, given that we need to check this fact to the unknown type, we are forced to implement such comparison method once per each descendant of class A, but this may be simplified using #define.
Summing up, I would probably write it like this:
#define TYPE_COMPARISON \
virtual bool compare(A* rhs) \
{ \
return dynamic_cast<decltype(this)>(rhs) != nullptr; \
}
class A {
public:
TYPE_COMPARISON
};
template <typename T>
class B : public A {
public:
TYPE_COMPARISON
};
class Registry {
private:
std::vector<A *> list;
public:
void append(A * a) {
int found = 0;
for (A * el : list) {
if (a->compare(el) && el->compare(a)) {
found = 1;
break;
}
}
if (!found)
list.push_back(a);
}
int size() {
return list.size();
}
};
Also, such method allows you to define whether or not a particular descendant class should be treated as being distinct with its parent.

Passing an array of Child objects to a function that accepts Parent*

I am working on an embedded platform with limited capabilities, so vectors/STL are not available.
This may be a trivial problem, but I do not have much experience in C++ (only C and C#, which may make me blind to an obvious c++ way to do it).
Consider the following example:
class Parent {
};
class Child : public Parent {
};
void Test(Parent* parents, uint8_t parentCount) {
// Accessing parent[x] is problematic when 'parents' contains a derived type
}
int main() {
// This is OK
Parent parents[3];
Test(parents, 3);
// This causes problems
Child children[3];
Test(children, 3);
return 0;
}
Obviously it is problematic to iterate over parents in Test(), if a pointer to an array of derived classes is provided, because the memory footprint of Parent is assumed during the iteration.
The only solution I see is to pass an array of pointers of type Parent (Parent** parents), but that seems cumbersome. Is there some C++ mechanism I am not aware of, like passing the array as a reference or something?
You could use this approach:
template <class T>
void Test(T* parents, uint8_t parentCount) {
// Code that accesses parent[x]
}
and then use it like this:
int main() {
Parent parents[3];
Test(parents, 3);
Child children[3];
Test(children, 3);
return 0;
}
If template is not an option and when the user of Test can not depend on Child and can't even know it's size, then you can use an array of pointers:
void Test(Parent** parents, uint8_t parentCount);
int main() {
Child children[n];
Child* pointers[n];
for(int i = 0; i < n; i++)
pointers[i] = &children[i];
Test(pointers);
}
Note that in this trivial example, we do know the size of the object whose pointers we pass, but in general, we may not be able to make that assumption for all users of Test.
If you can't use templates, you can do this:
class Parent {
};
class Child : public Parent {
};
void Test(Parent* parents, uint8_t parentCount, uint16_t parentSize) {
for (uint8_t ii = 0; ii < parentCount; ++ii) {
void* parentvoid = reinterpret_cast<char*>(parents) + ii * parentSize;
Parent* parent = parentvoid;
}
}
int main() {
Parent parents[3];
Test(parents, 3, sizeof(parents[0]));
Child children[3];
Test(children, 3, sizeof(children[0]));
}

how to build a tree structure in C++ using std::map

I am trying to write a tree sort of structure in C++. As in every tree there are branches and leaves. A branch can contain other branches as well as leaves.
Now my implementation calls for each branch and leaf to have different functionalities. So for example.
Take the tree structure
Root
| |
Branch1 Branch2 Branch3
| | |
Leaf1 Leaf2 Branch4
Now Each Leaf and branch has a different function to execute so Leaf1 will have a function called leaf1_func, Leaf2 will have leaf2_func, Branch4 has Branch4_func.
I was initially trying to implement composite design pattern. But that means I would have as many classes as leafs. But since I have tons of leaves and branches I would like to avoid creates more classes. I realize this is an unusual situation but was hoping somebody could help me in this regard. What would be the best way to implement this tree without creating too many classes.
i am using map STL container to store datas as well, i want to use this tree implementation to solve this in TSP problem.
#include <cstdlib>
#include <iostream>
#include <map>
using namespace std;
int n=4;
int min=1, max=10;
struct graph
{
int nodes;//total no. of nodes or vertices namely cities
std::map<std::pair<int,int>, int> graphMap;//an object that links a pair of vertices
};
void directed_Graph(graph);
void directed_Graph(graph G)
{
//int n = G->nodes; //city count
int i, j;
for(i = 0; i <= n-1; i++)
{
for(j = 0; j <= n-1; j++)
{
if(i!=j)
{
G.graphMap[std::make_pair(i,j)] = (rand()%10)+1;
//cout<<G.graphMap[std::make_pair(i,j)]<<"\n";
}
else
{
G.graphMap[std::make_pair(i,j)] = 0;
}
}
}
}
int main(int argc, char** argv)
{
graph g;
g.nodes = 4;
directed_Graph(g);
return 0;
}
Different functions with the same signature do still have the same type. Even if the functions are completely unrelated, you can have a tree that stores random data by using void * (type erasure) and then typecast back to the known actual type after the leaf node is reached.
struct node {
void (*fptr)(); // pointer to any function taking no args, no return
void *data; // pointer to anything, need to cast before using
};
void f() { std::cout << "hello"; }
void g() { std::cout << "world"; }
node a = { f, f };
node b = { g, g };
a.fptr();
static_cast< void (*)() >( b.data )();
You could also use virtual methods with inheritance and store pointers to base class type in the tree. It depends on what the nodes really are.
None of this is really related to the fact it goes into a graph.
From the look of you diagram it seems that you want a tree where the nodes can have more than two children. If that's the case then the STL containers are not going to work for you. They are are self balancing binary trees.
If you're OK with a binary tree then there are a couple ways to do this. The first is to write functions and then to store function pointers or functors in the tree.
#include <set>
int foo( ) {
return 5;
}
std::set< int (*)( ) > my_set;
my_set.insert( &foo );
The problem with this approach is that all of your functions have to have the same type, i.e. take the same arguments and have the same return type. What's more, while they can define different behaviors, they cannot keep state, i.e. you cannot store data in a function pointer.
The second options, as you mentioned, is to write classes. If you need to vary the behavior of the nodes then the best way to do that is to define an interface and use polymorphism.
#include <set>
#include <iostream>
struct base {
virtual void print( ) const = 0;
};
struct derived1 : public base {
void print( ) const { std::cout << "derived1" << std::endl; }
};
struct derived2 : public base {
void print( ) const { std::cout << "derived2" << std::endl; }
};
std::set< base* > my_set;
my_set.insert( new derived1( ));
my_set.insert( new derived2( ));
You did not say whether you need to force certain behaviors to be leaves and other to be internal nodes, or if the nodes need to be ordered in a particular way, but if you do then you may be able to accomplish this by creating a custom less-than function:
bool operator < ( base const * const b1, base const * const b2 ) {
// Figure out which is less here.
}
Again, if you need something that isn't a binary tree, though, then you're out of luck. And any way you slice this you will need to write some code implementing the behavior stored in each node, whether it's functions or classes.
if you have limited depth of tree it's convenient to describe it like this:
typedef std::map<std::string, double> action_map_t;
typedef std::map<std::string, action_map_t> objid_map_t;
typedef std::map<std::string, objid_map_t> objtype_map_t;
//....etc here is depth == 3
objtype_map_t m_mapTooltipDuration;
m_mapTooltipDuration[objtype][objid][action] = atof(duration.c_str());

Class Return Type Overloading

I commonly run into the following situation where I have a data structure which I'd like to have access as follows:
class data {
public:
double error;
double value;
...
}
...
data *outputs;
...
double lastValue = ...;
double someValue = ...;
for (int i = 0; i < n; ++i) {
outputs[i] = someValue; //should be equivalent to outputs[i].value = someValue
outputs[i].error = lastValue - someValue;
}
Currently I just use outputs[i].value = but, for readability purposes, it actually would make more sense to use (something similar to) the above example (at least from a theory point of view, the code doesn't require maintainability).
I understand that operator= would work for the above situation, but what about a simple access, I'd still have to use outputs[i].value. What would be the best solution to this for readability for both the conceptual design and also without causing headaches for the programmer.
You can add an assignment operator overload to data:
class data {
public:
double error, value;
void operator=(double d) { value = d; }
};
Though, to be honest, I think this would be rather confusing. It depends on how you intend to use it, of course, but given your example, I think it would be cleaner to add a constructor for the class:
class data {
public:
double error, value;
data(double value_arg, double error_arg)
: value(value_arg), error(error_arg) { }
};
used as:
outputs[i] = data(someValue, lastValue - someValue);