I set up a "parent class pointer" vector with size 2 to store its "derived class" address but seem like this vector only stores final address no matter how many address i added, so its cause "Access violation reading" problem. By the way i used composite pattern.
I've tried many ways, i've used vector, 2d pointer (Ex: int**).
class Node{
public:
virtual double evaluate();
};
class NumNode: public Node{
private:
double number;
public:
double evaluate();
NumNode(int);
};
class OpNode: public Node{
private:
char operation;
vector<Node*> branch;
public:
double evaluate();
void addLeft(NumNode);
void addRight(NumNode);
OpNode(char);
};
double OpNode::evaluate(){
if(this->operation == '+')
return this->branch[0]->evaluate() + this->branch[1]-
>evaluate();**Exception thrown at 0x008C6097 in
Project_Testing.exe: 0xC0000005: Access
violation reading location 0xCCCCCCCC.**
return 0;
}
void OpNode::addLeft(NumNode other){this->branch[0] = &other;}
void OpNode::addRight(NumNode other){this->branch[1] = &other;}
int main(){
OpNode n('+');
n.addLeft(NumNode(2));
n.addRight(NumNode(3));
cout << n.evaluate() << endl;
}
As you look into the main funciton, i've add two diffrent NumNode. But when i started debugging.
branch[0] 0x006ff620 {...} Node *
branch[1] 0x006ff620 {...} Node *.
They had the same address!
You issue is here:
void OpNode::addLeft(NumNode other){this->branch[0] = &other;}
void OpNode::addRight(NumNode other){this->branch[1] = &other;}
As mentioned in comment:
Your addLeft and addRight take the address of the stack parameter other. Since the stack looks exactly same for both calls, you see exactly the same address. Either pass in a real pointer that can be stored directly, or (in your methods) allocate a copy (with new NumNode(other)) and store that address.
Another way around it you will probably wan't for nodes is using std::shared_ptr
So your nord list becomes:
vector<shared_ptr<Node> > branch;
and then:
void OpNode::addLeft(const shared_ptr<NumNode> >& other){this->branch[0] = other;}
You are taking pointer to temporary object. When this objects lifetime ends referencing it is an Undefined Behavior, what in this case ends with a crash.
Create this objects on heap to extend lifetime of required objects.
For example:
class Node{
public:
virtual ~Node() {}
virtual double evaluate();
};
class NumNode: public Node {
private:
double number;
public:
double evaluate();
NumNode(int);
};
class BinaryOpNode: public Node{
private:
std::unique_ptr<Node> left;
std::unique_ptr<Node> right;
public:
BinaryOpNode(std::unique_ptr<Node> a, std::unique_ptr<Node> b)
: left{std::move(a)}
, right{std::move(b)}
{
}
double evaluate() {
return binaryOperator(left->evaluate(), right->evaluate());
}
virtual double binaryOperator(double a, double b) = 0;
};
class AddOpNode : public BinaryOpNode {
public:
using BinaryOpNode::BinaryOpNode;
double binaryOperator(double a, double b) { return a + b; }
};
int main(){
AddOpNode n {
std::make_unique<NumNode>(2),
std::make_unique<NumNode>(3)
};
cout << n.evaluate() << endl;
return 0;
}
User contributions licensed under CC BY-SA 3.0