casting shared pointer from B class to A class is not working the console output isn't 12 it's (it outputs A's x but i want B's x)(probably an other memory address). what's wrong with my code
#include <iostream>
#include <memory>
class A
{
public:
int x;
};
class B : public A
{
public:
B(){}
B(const B*){}
int x = 12;
};
std::shared_ptr<A> create()
{
return std::make_shared<B>(new B);
}
int main(){
std::shared_ptr<A> p;
p = create();
std::cout << p->x << std::endl;
std::cin.get();
return 0;
}
A::x and B::x are different objects. Variable access is never polymorphic in C++, so when you access p->x, you're accessing A::x. A::x was never initialized though, so the behavior of your program is undefined.
You need to either have your derived class's constructor initialize the base class's object or delegate that responsibility to the base class's constructor:
class A
{
public:
A(int x) : x{x} {}
int x;
};
class B : public A
{
public:
B() : A{12} {}
};
Live Demo
Alternatively you could wrap x in a virtual accessor method:
class A
{
public:
virtual ~A() = default;
virtual int x() const = 0;
};
class B
{
public:
int x() const override
{
return x_;
}
private:
int x_ = 12;
};
Live Demo
Related
I'm new to polymorphism and I'm trying to learn how this exactly works .
I want for example to get the print() function of class Y and use it in the base class .
Is this possible to do ?
class A
{
public:
A() = default;
virtual void print()
{
//Is it possible to get the print() function of class Y here ?
};
};
class B : public A
{
public:
B() = default;
void print(){ std::cout << "B " << std::endl;}
};
class C : public A
{
public:
C() = default;
void print(){ std::cout << "C " << std::endl;}
};
class Y : public C , public B
{
public:
Y() = default;
void print()
{
B::print();
C::print();
}
};
int main()
{
A a;
a.print();
return 0;
}
Your main() is creating an A object directly, not a Y object. That is why you are not seeing the output you want. Polymorphism only works when accessing derived class objects via base class pointers/references, eg:
int main()
{
Y y;
A *a = static_cast<C*>(&y);
a->print();
return 0;
}
int main()
{
Y y;
A &a = static_cast<C&>(y);
a.print();
return 0;
}
The reason for the type cast is becauseY has 2 A portions, one from B and one from C, so you have to help the compiler a little by specifying which A you want to point to.
So to summarize I have something equivalent to
class A{
public:
virtual void foo() const = 0;
};
class B : public A{
public:
B(){};
void foo() const override{
//some code
};
};
class C{
public:
C(){};
B someFunction();
private:
A* x;
};
and A* x; points to some B object and I need someFuntion() to return that object that x is pointing to. I've tried just doing return *x but that doesn't work.
You must down-cast the x into B before de-reference.
class C
{
public:
C() {};
B someFunction()
{
return *static_cast<B*>(x); // like this
}
private:
A* x = new B;
};
You need also provide the virtual ~A(), not to have undefined behavior.
When to use virtual destructors?
class A
{
public:
virtual void foo() const = 0;
virtual ~A() = default;
};
If you know that x points to a B object then cast it first.
return *static_cast<B*>(x);
I came across this code in a past exam:
#include <iostream>
class cls1
{
protected:
int x;
public:
cls1()
{
x = 13;
}
};
class cls2 : public cls1
{
int y;
public:
cls2()
{
y = 15;
}
int f(cls2 ob)
{
return (ob.x + ob.y);
}
};
int main()
{
cls2 ob;
std::cout << ob.f(ob);
return 0;
}
This works just fine and outputs 28. The problem is, it seems to contradict with this code (found in another exam):
#include <iostream>
class B
{
protected:
int x;
public:
B(int i = 28)
{
x = i;
}
virtual B f(B ob)
{
return x + ob.x + 1;
}
void afisare()
{
std::cout << x;
}
};
class D : public B
{
public:
D(int i = -32)
: B(i)
{
}
B f(B ob)
{
return x + ob.x - 1;/// int B::x is protected within this context
}
};
int main()
{
B *p1 = new D, *p2 = new B, *p3 = new B(p1->f(*p2));
p3->afisare();
return 0;
}
It's the same type of hierarchy, but one has access to ob.x and the other one doesn't. Can someone explain to me why that is?
The difference is, in the 1st case the protected member is accessed through the derived class. In the 2nd case the protected member is accessed through the base class, which is not allowed.
For protected members,
(emphasis mine)
A protected member of a class is only accessible
2) to the members and friends (until C++17) of any derived class of that class, but only when the class of the object through which the protected member is accessed is that derived class or a derived class of that derived class:
struct Base {
protected:
int i;
private:
void g(Base& b, struct Derived& d);
};
struct Derived : Base {
void f(Base& b, Derived& d) { // member function of a derived class
++d.i; // OK: the type of d is Derived
++i; // OK: the type of the implied '*this' is Derived
// ++b.i; // error: can't access a protected member through
// Base (otherwise it would be possible to change
// other derived classes, like a hypothetical
// Derived2, base implementation)
}
};
I stumbled upon casting sideways from derived to derived class and discovered a gap in my knowledge. I had been living in a world where this is possible - until now. Instead, std::bad_cast is thrown. What's going on here?
#include <iostream>
class Base
{
protected:
int x_;
public:
Base(int x) : x_(x) {}
virtual ~Base() = default;
int x() const { return x_; }
virtual void setX(int x) = 0;
};
class Editable : public Base // class implements setters
{
public:
Editable(int x) : Base(x) {}
void setX(int x) { x_ = x; }
};
class ReadOnly : public Base // class implements empty setters
{
public:
ReadOnly(int x) : Base(x) {}
void setX(int x) {}
};
int main()
{
Editable editable(4);
ReadOnly &readOnly = dynamic_cast<ReadOnly&>(editable); // std::bad_cast
}
This is what is meant when people say that dynamic_cast can cast sideways:
struct A { virtual ~A() = default; };
struct B { virtual ~B() = default; };
struct D : A, B {};
B* pb = new D();
A* pa = dynamic_cast<A*>(pb); // OK
i.e., it allows you to cast a B* to a A* if the pointer is pointing to something that's derived from both A and B. For the cast to succeed, there still must be an A subobject for the pointer to point to (or the reference to bind to, if you are casting to a reference type).
In your case, e is an Editable. There's no ReadOnly subobject anywhere in there. So the cast fails.
You're not casting sideways.
You're casting from one derived of a base to another.
Let's hypothetically say your cast succeeded, and there's a public int member called readOnlyInt in ReadOnly class.
How can the compiler perform readonly.readOnlyInt?
There's no readOnlyInt in the casted ReadOnly & cause it is in fact an Editable.
Casting sideways involves multiple inheritance structures & looks something like this:
class A {
virtual ~A() {}
};
class B {
virtual ~B() {}
};
class C : public A, public B {
};
int main() {
B *b = new C();
A *a = dymanic_cast<A *>(b);
return 0;
}
So I'm trying to write a copy constructor for class E such that it will get every int x from each class and assign it to its counterpart. How do I cast the right side?
class A
{
public:
int x;
};
class B: public virtual A
{
public:
int x;
};
class C: public virtual A
{
public:
int x;
};
class D : public B, public C
{
public:
int x;
};
class E: public D
{
public:
int x;
E(const E& e)
{
E::x = (E)e.x // problem
D::x = ?
C::x = ?
B::x = ?
A::x = ?
}
};
You do not need to cast an int to assign it to an int. Just do:
self->x = ((E)e).x;
D::x = ((D)e).x;
E::x = e.E::x;
D::x = e.D::x;
C::x = e.C::x;
B::x = e.B::x;
A::x = e.A::x;
Though it might be wiser to give each class a suitable copy constructor, with a suitable initialization list invoking copy constructors of base classes.