Inheritance from abstract base class for decision tree

Hi, I'm trying to implement a decision tree that gets doubles as input (in this sample code just random numbers) and returns a boolean value. At the nodes, I'd like to use various operators that can have different input and return types. I've implemented an abstract base class for the nodes and I'm deriving the specific nodes from it. In the code below, I've included only a few derived classes. Building the tree (randomly) is no problem. However, I'm looking for a clever way to evaluate the tree. I think that uncommenting the lines in bold print would in principle do it. However, this is not possible because "value" is not a member of the base class. The type of "value" is different in the derived classes, so I cannot simply declare it in the base class. Can you suggest a nice way to make this work? Should I use a class template? Thanks!

"Node.h"
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
#pragma once

class NodeBase{
public:
	NodeBase* Child_1;
	NodeBase* Child_2;
	virtual void evaluate() = 0;
};

class And : public NodeBase{
public:
	bool value;
	And();
	bool f(bool x, bool y);
	void evaluate();
};

class Larger : public NodeBase{
public:
	bool value;
	Larger();
	bool f(double x, double y);
	void evaluate();
};

class InputValue : public NodeBase{
public:
	double value;
	InputValue();
	void evaluate();
};



"Node.cpp"
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
#include <iostream>
using namespace std;

#include "Node.h"

And::And(){
	if (rand() > 2 * RAND_MAX / 3) Child_1 = new And; 
	else Child_1 = new Larger;
	if (rand() > 2 * RAND_MAX / 3) Child_2 = new And;
	else Child_2 = new Larger;
}

bool And::f(bool x, bool y){ return x && y; }

void And::evaluate(){
	(*Child_1).evaluate();
	(*Child_2).evaluate();
	//value = f((*Child_1).value, (*Child_2).value);
}


Larger::Larger(){
	Child_1 = new InputValue;
	Child_2 = new InputValue;
}

bool Larger::f(double x, double y){
	if (x > y) return true;
	else return false;
}

void Larger::evaluate(){
	(*Child_1).evaluate();
	(*Child_2).evaluate();
	//value = f((*Child_1).value, (*Child_2).value);
}


InputValue::InputValue(){
}

void InputValue::evaluate(){
	value = rand() / double(RAND_MAX);
}



"main.cpp"
1
2
3
4
5
6
7
8
#include <iostream>
using namespace std;
#include "Node.h"

int main(){
	And root;
	root.evaluate();
}
Get rid of f, evaluate should return a value, the classes should be constructed with their operands.
Hi L B, thanks for your suggestions! I see that f is superfluous.
I'm not sure how to let "evaluate" return a value. Depending on the derived class, evaluate should return a different type (boolean or double). So I guess I cannot declare it as a virtual function in the base class. And if it is not declared in the base class, I cannot access it using the "(*Child_1).evaluate();" Probably I'm mistaken at some point...?
You will want to have a Value class that stores what type of information it holds and the information itself, along with functions to get the information as any other type. How do you think scripting languages work? ;)
OK, thanks again, I haven't thought of that. I will try to make it work.
Topic archived. No new replies allowed.