catdoanything33 catdoanything33 - 1 month ago 7
C++ Question

Properly passing pointer from function C++

It crashes on

s_r->info
because
s_r
is not pointing on
obj2
. Function
search_recurs()
should find the pointer and return result. It should find the right pointer because result points on
obj2
.

But something happens when returning the result because
s_r
(where
s_r=search_recurs()
returns the result) does not point on the same object as result, which should be returned from search.

Output:

W Funkcji search:
Name: zmiana2d
Parameter_a : 5
Parameter_d : 6
adres rzutowanie: 00AFFC50
adres result: 00AFFC50

main:
adres obj2: 00AFFC50
adres s_r: 00AFFB04 //<======= Why is it not 00AFFC50 ?


CODE:

#include "stdafx.h"

using namespace std;


class Node {
private:

public:
string name;
Node *parent;
vector <Node*> children;


Node() { name = "noname", parent = NULL; }

Node(string _name) { name = _name, parent = NULL; }

Node(Node *_parent) { parent = _parent; }

Node(string _name, Node *_parent) { name = _name, parent = _parent; }

Node(Node *_parent, vector <Node*> _children) { parent = _parent, children = _children; }

Node(string _name, Node *_parent, vector <Node*> _children) { name = _name, parent = _parent, children = _children; }

virtual ~Node() { cout << "Base Destructor called\n"; }


void add_parent(Node *wsk) {
parent = wsk;
}

void add_children(Node *child) {
children.push_back(child);
}

void info_node() {
cout << "Name: " << name << endl;
cout << "Address: " << this << endl;
cout << "Parent: " << parent << endl;
}

};


class A {
private:
string name;
int parameter_a;
protected:

A() { name = "untitled"; parameter_a = 1; }
A(string _name) { name = _name, parameter_a = 1; }
A(string _name, int _parameter_a) : name(_name), parameter_a(_parameter_a) {};

string info_name() {
return name;
}

int info_parameter_a()
{
return parameter_a;
}

public:

char info_type() {
return 'A';
}

friend class Leaf;
friend A* search_recurs_node(Node* root, string name);
virtual void info() = 0;
};


class Leaf : public Node {
private:

public:
vector<A*> objects;
Leaf() { name = "noname", parent = NULL; }

Leaf(string _name) { name = _name, parent = NULL; }

Leaf(Node *_parent) { parent = _parent; }

Leaf(string _name, Node *_parent) { name = _name, parent = _parent; }

Leaf(Node *_parent, vector <Node*> _children) { parent = _parent, children = _children; }

Leaf(string _name, Node *_parent, vector <Node*> _children) { name = _name, parent = _parent, children = _children; }

void add_objects_leaf(A* obj) {
objects.push_back(obj);
}

};


class X : public A, public Leaf {
private:
int parameter_x;
public:
X() : A("dziedziczone_w_X_z_A", 98), parameter_x(99) {};
X(string _name_x, int _parameter_a, int _parameter_x) : A(_name_x, _parameter_a), parameter_x(_parameter_x) {};


char info_type() {
return 'X';
}


void info() {
cout << "Name: " << A::info_name() << endl;
cout << "Parameter_a : " << A::info_parameter_a() << endl;
cout << "Parameter_d : " << parameter_x << endl;
}



};



A* search_recurs_node(Node* root, string name) {


A* result;
Leaf* rzutowanie;

if ((root->children.size()) > 0) {
for (int i = 0; i < (root->children.size()); ++i) {

search_recurs_node(root->children[i], name);

}
}
else if (rzutowanie = dynamic_cast<Leaf*>(root)) {
for (int i = 0; i < rzutowanie->objects.size();++i) {
if (rzutowanie->objects[i]->info_name() == name) {
cout << "W Funkcji search: " << endl;
rzutowanie->objects[i]->info();
cout << endl << "adres rzutowanie: " << rzutowanie->objects[i] << endl;
result = (rzutowanie->objects[i]);
cout << "adres result: " << result << endl;
cout << endl;
return result;
}
}
}


//return NULL;

};

int main()
{
//

Node A_node("node_A");
Leaf X_node("node_X", &A_node);

A_node.add_children(&X_node);

X obj1("name d1", 1, 2), obj2("zmiana2d", 5, 6);

X_node.add_objects_leaf(&obj1);
X_node.add_objects_leaf(&obj2);


A* s_r;
s_r = search_recurs_node(&A_node, "zmiana2d");

cout << "main: " << endl;
cout << "adres obj2: " << &obj2 << endl;
cout << "adres s_r: " << s_r << endl;

s_r->info();

cout << endl << "The cause of 90% of programming errors sits in front of the screen" << endl;

return 0;
}

Answer

Preliminary remark

obj2 is of type X, which inherits from A and from Leaf.

You return a pointer to an A. But the A subobject is embedded in X with Leaf; This is why you could get another address. You should convert it to an X* to be sure to have exactly the same address, whatever the layout of your class:

 X* x_r = dynamic_cast<X*>(s_r);   // you can, because there's a virtual fct
 if (x_r) 
    cout << "adres x_r: "<<x_r<<endl; 
 else cout << "couldn't cast"<<endl; 

By the way, think to add a virtual destructor for any class that has a virtual function.

The root cause of your problem

Your recursive search function doesn't work: you call it recursively, but you're not doing anything with the result. Change as follows:

...
if ((root->children.size()) > 0) {
    for (int i = 0; i < (root->children.size()); ++i) {
        auto a= search_recurs_node(root->children[i], name);  // <== keep response returned
        if (a)                                    // <== if value already found
           return a;                              // <== return it
    }    
}
...

It would be wise to return nullptr at the end of your function (why did you comment it out ?)

Online demo