Could someone explain what is wrong here?

Hello,

I have a code that gives wrong output. I have 3 classes, i.e., Material, Elastic and Solver. The Material is a parent class and the Elastic is derived from the Material class. My main function creates an object of Solver class and then passes a value through the SetMaterial function, which in turn creates an Elastic class object and sets values for a parameter in the Elastic class. When I try to retrieve that value through the GetValue function I get a wrong value.

Could someone please explain to me what is wrong here.



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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#include <iostream>
#include<vector>


class Material
{
    public:
        Material()
        {
            std::cout << " this is Material" << std::endl;
        }

        virtual void SetValue(double val){}
        virtual void GetValue(std::vector<double> & stt){}
};

class Elastic : public Material
{
    public:
        Elastic()
        {
            std::cout << " this is Elastic" << std::endl;
        }

        void SetValue(double val)
        {
            Value = val;
            std::cout << " param set "<< Value << std::endl;
        }

        void GetValue(std::vector<double> & stt)
        {
            std::cout << " param get "<< Value << std::endl;
            stt[0]=Value;stt[1]=Value;stt[2]=Value;
        }

    private:
        double Value;
};

class Solver
{
    public:
        Solver()
        {
            std::cout << " this is solver" << std::endl;
        }
        void Solve()
        {
            std::vector<double> va(3,0.0);
            mobj->GetValue(va);
            std::cout << va[0] << " " << va[1]<< std::endl;
        }

        void SetMaterial(double val)
        {
            Elastic eobj;
            mobj = & eobj;
            mobj->SetValue(val);
        }

    private:
        Material *mobj;
};



int main()
{
    Solver sobj;
    sobj.SetMaterial(2.1);
    sobj.Solve();

}





this is solver
this is Material
this is Elastic
param set 2.1
param get 0
0 0

Last edited on
The Elastic object that you create on line 57 is a local variable that only exists for as long as the function runs, so later when Solve() is called it tries to retrieve the value from a non-existing object which will obviously not work.
Last edited on
Thanks, Mr Peter for your reply.

If I change the code slightly, i.e. replace std::vector<double> in the lines 14, 31 and 50 with double, then the code works perfectly.

How is that possible? See the modified code and output.

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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#include <iostream>
#include<vector>


class Material
{
    public:
        Material()
        {
            std::cout << " this is Material" << std::endl;
        }

        virtual void SetValue(double val){}
        virtual void GetValue(double & stt){}
};

class Elastic : public Material
{
    public:
        Elastic()
        {
            std::cout << " this is Elastic" << std::endl;
        }

        void SetValue(double val)
        {
            Value = val;
            std::cout << " param set "<< Value << std::endl;
        }

        void GetValue(double & stt)
        {
            std::cout << " param get "<< Value << std::endl;
            stt=Value;
        }

    private:
        double Value;
};

class Solver
{
    public:
        Solver()
        {
            std::cout << " this is solver" << std::endl;
        }
        void Solve()
        {
            double va;
            mobj->GetValue(va);
            std::cout << va << std::endl;
        }

        void SetMaterial(double val)
        {
            Elastic eobj;
            mobj = & eobj;
            mobj->SetValue(val);
        }

    private:
        Material *mobj;
};



int main()
{
    Solver sobj;
    sobj.SetMaterial(2.1);
    sobj.Solve();

}




this is solver
this is Material
this is Elastic
param set 2.1
param get 2.1
2.1 

Since the program is incorrect there isn't really any guarantees what will happen. This is called undefined behaviour. You might be able to figure out why things happen the way they do by looking at the assembly that the compiler generates but it's not very useful information, and the behaviour could easily change when you change compiler settings or just change some other part of the code which could trigger different optimizations to happen.
Last edited on
Thanks a lot for your help. Now, I have moved "Elastic eobj;" to make that private. So Elastic is not a local object any more and my code works fine.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Solver
{
    public:
        Solver()
        {
            std::cout << " this is solver" << std::endl;
        }
        void Solve()
        {
            std::vector<double> va(3,0.0);
            mobj->GetValue(va);
            std::cout << va[0] << " " << va[1] << " " << va[2] << std::endl;
        }

        void SetMaterial(double val)
        {
            mobj = & eobj;
            mobj->SetValue(val);
        }

    private:
        Material *mobj;
        Elastic eobj;
};
Why not remove mobj and just use eobj in all the functions?
Well, I am writing a Finite Element code. So the idea is to create a parent class which can be pointed to different material classes depending on the user's input. So, like Elastic, I have 4-5 other classes which are derived from the parent Material class and I have a if-elseif statement somewhere in my code to do *mobj = & eobj . That is why I need to keep mobj in my code.
Topic archived. No new replies allowed.