Have some issues with my code. It return a strange address instead of class parameters values. Can anyone help me , please ?

Hey there !
I have an issue with my code , something about my virtual function and input/output operator and i don't know how to fix it.

I apologise in advance , i know this **question is very long** (*exemples are long as well but they are part of a way longer code. tried to cut them as much as possible and still to understand how those classes work and where the problem is*)

First thing, i writed 2 classes ( with inheritance) . Class A and B like this :

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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
    class A{
    
    protected:
        int x;
    
    public:
    
        A()
        {
            x=0;
        }
    
        A(int x1)
        {
            x=x1;
        }
    
        A(const A &o1)
        {
            x=o1.x;
        }
    
        A &operator=(const A &o1)
        {
          x=o1.x;
        }
    
        friend istream &operator>>(istream &input, A &o1)
        {
            input >> o1.x;
            return input;
        }
        friend ostream &operator<<(ostream &output, const A &o1)
        {
            output << o1.x;
            return output;
        }
        virtual void cin2()
         {
             cin >> *this;
         }
    
        friend class C;
    };
    
    
    class B: public A{
    
    protected:
        float y;
    
    public:
        B(): A()
        {
            y=0.0;
        }
    
        B(int x1, float y1): A(x1)
        {
            y=y1;
        }
    
        B(const B &o2): A(o2)
        {
            y=o2.y;
        }
    
        B &operator=(const B &o2)
        {
            y=o2.y;
            A::operator=(o2);
            return *this;
        }
    
         friend istream &operator>>(istream &input, B &o2)
        {
            input >> (A&) o2;
            input >> o2.y;
            return input;
        }
        friend ostream &operator<<(ostream &output, const B &o2)
        {
            output << (A) o2;
            output << o2.y;
            return output;
        }
    
         void cin2()
         {
             cin >> *this;
         }
    };


Tested and output & input operators works good in those 2 classes. The virtual method is used below ( explanations there)

Next, i wanted a class that have an object from class A inside of it. I readed about composition and tried to do something similar. Here is the class C:

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
    class C{
    
    protected:
        A* obj;
        double z;
    
    public:
        C()
        {
            obj=new A;
            z=0;
        }
    
        C(double z1, const A &obj1)
        {
            obj=new A(obj1);
            z=z1;
        }
    
        C(const C &o3)
        {
            obj=o3.obj;
            z=o3.z;
        }
    
        C &operator=(const C &o3)
        {
            obj=o3.obj;
            z=o3.z;
            return *this;
        }
    
        friend istream &operator>>(istream &input, C &o3)
        {
            input >> o3.z;
            B obj2;
            o3.obj=&obj2;
            o3.obj->cin2();
            return input;
        }
    
        friend ostream &operator<<(ostream &output, const C &o3)
        {
            output << o3.z << '\n';
            operator<<(output, (B&)o3.obj);
            output << '\n';
            return output;
        }
    };


Now here comes the problem.
As i said above, i writed a virtual function and called it here because:

When i read ( cin >>) a class C object, i will automatically read a class A object as well. What i wanted was to go throught class A to his child, class B, and cin (read) both classes parameters from there. ( since class B operator>> is used to cin class A parameters as well).

That worked ( every time i read a class C object it requires me to input values for class A and B parameters as well).
What didn't work was printing what i've just read ( cout << ). I run the code, it's print me class C parameter ( double z) but after that, when it should print the values gived for class A and B parameters, it print some kind of address( i specified that o3.obj is now a class (B&) , and i think it shouldn't do that, though i'm not very sure)
How can i make it works right?

This is main:
1
2
3
4
5
6
7
8
9
10
    int m;
        cin >>m;
        C* v=new C[m+1];
    
        for(int i=1; i<=m;++i)
            cin >> v[i];
        cout << '\n';
        for(int i=1;i<=m;++i)
            cout << v[i];
        return 0;


My input:

1 /// numbers of objects
10 /// class C parameter (float z)
11 /// class A parameter (int x)
10.1 /// Class B parameter (float y)

My output:

10 /// value of class C parameter
494590 /// ? some address

Now , you probably think that it was easyer if class C had an object from class B inside ( that way a virtual function is not required because if we use class B input( cin >>), it will automatically read values for class A parameters as well.) Well, it is easyer, but not satisfying what i wanted. Also, i readed about downcasting, dynamic_cast, and probably this is how can i solve this problem in a smart way, but i don't understand exactly where and how to use dynamic_cast.

I will highly appreciate if you can answer me with some exemples as well ( to understand better what to do here).
Probably the answer is very simple and im too dumb to find it myself

Im very excited to find out the answer. If you have the time, please help me out.
Last edited on
The way you've written C, C::obj can only point to an instance of A and never to an instance of B, since every constructor of C explicitly initializes C::obj to a newly allocated instance of C.
If you want C::obj to behave polymorphically then C's constructors need to accept an instance of A.
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 C{
protected:
    std::unique_ptr<A> obj;
    double z;
public:
    C(std::unique_ptr<A> &&o){
        this->obj = std::move(o);
        this->z = 0;
    }
    C(double z1, const A &obj1){
        this->obj = obj1.clone(); //Polymorphic. Returns a new std::unique_ptr<A>
        this->z = z1;
    }
    C(const C &o3){
        this->obj = o3.obj->clone();
        this->z = o3.z;
    }
    friend ostream &operator<<(ostream &output, const C &o3){
        output << o3.z << '\n';
        this->o3->cout2(); //Polymorphic.
        output << '\n';
        return output;
    }
};


Needless to say, downcasting a pointer-to-base to a pointer-to-derived unconditionally and then using a member of the derived class is highly unsafe.
Last edited on
dynamic_cast should be used to safely convert pointers and references to classes up, down, and sideways along the inheritance hierarchy.

See https://en.cppreference.com/w/cpp/language/dynamic_cast
1
2
3
4
5
6
7
8
        friend istream &operator>>(istream &input, C &o3)
        {
            input >> o3.z;
            B obj2;
            o3.obj=&obj2;    // o3.obj now points to obj2.
            o3.obj->cin2();  // calls B::cin2()
            return input;    // destroys obj2 and returns. Now o3.obj points to junk.
        }

Topic archived. No new replies allowed.