Using shared_from_this() with derived class - c++

When I try to run this code:
class A : public enable_shared_from_this<A> {
public:
A() {
cout << "A::A()" << endl;
};
virtual ~A() {
cout << "A::~A()" << endl;
};
virtual void func() {
cout << "A::func" << endl;
auto ptr = shared_from_this();
ptr->dosomething();
}
virtual void dosomething() {
cout << "A::dosomething" << endl;
}
};
class B : public A {
public:
B() {
cout << "B::B()" << endl;
};
~B() {
cout << "B::~B()" << endl;
};
void func() override {
cout << "B::func" << endl;
A::func();
}
void dosomething() override {
cout << "B::dosomething" << endl;
}
};
int main() {
shared_ptr<B> pb = make_shared<B>();
//shared_ptr<A> pa = make_shared<A>();
pb->func();
}
The result I get is:
A::A()
B::B()
B::func
A::func
B::dosomething
B::~B()
A::~A()
The call chain is B::func->A::func->ptr->dosomething, this indicates that the return value of shared_from_this() is a shared_ptr<B>.
Why is the result of calling shared_from_this() not shared_ptr<A>?

Related

Virtual destructor of an inherited template class

Can any one explain how delete x works correctly without virtual ~X()
#include <iostream>
struct B
{
B()
{
std::cout << "B()" << std::endl;
}
virtual ~B()
{
std::cout << "~B()" << std::endl;
}
};
struct C : B
{
C()
{
std::cout << "C()" << std::endl;
}
virtual ~C()
{
std::cout << "~C()" << std::endl;
}
};
template <class T>
struct X : T
{
X()
{
std::cout << "X()" << std::endl;
}
~X()
{
std::cout << "~X()" << std::endl;
}
};
template <class T>
struct Y : X<T>
{
Y()
{
std::cout << "Y()" << std::endl;
}
~Y()
{
std::cout << "~Y()" << std::endl;
}
};
int main()
{
std::cout << "====" << std::endl;
{
B* b = new C;
delete b;
}
std::cout << "====" << std::endl;
{
X<C>* x = new Y<C>;
delete x;
}
std::cout << "====" << std::endl;
return 0;
}
Output:
====
B()
C()
~C()
~B()
====
B()
C()
X()
Y()
~Y()
~X()
~C()
~B()
====
It is virtual – X<C> inherits C, the root of the hierarchy is B, and the destructor is declared virtual in B.
The class templating is completely irrelevant; it works exactly as it would if you had
struct X : C
{
X() { std::cout << "X()" << std::endl; }
~X() { std::cout << "~X()" << std::endl; }
};
struct Y : X
{
Y() { std::cout << "Y()" << std::endl; }
~Y() { std::cout << "~Y()" << std::endl; }
};
and
X* x = new Y;
delete x;

Virtual void, classes, constructors, polymorphism - order of execution

I have problem with understanding order of execution in virtual void/polymorphism based program.
As far as I understand what happens in other outputs, I have no idea why those commands:
a->b();
d->b();
d->a();
((G*)d) -> a();
give following outputs:
Nieznany
Nieznany
Gniewosz
Could anyone please explain me why those 3 methods print results as above?
#include <iostream>
using namespace std;
class C { public:
C() {cout << "Buduje A";}
void a() {cout << "Nauczyciel" << endl;}
virtual ~C() {cout << "~D" << endl;}
virtual void b() {cout << "Nieznany" << endl; }; };
class G {
int e; public:
G() {cout << "Buduje G ";}
void a() {cout << "Gniewosz " << endl;}
~G() {cout << "~C " << endl; }
void b() {cout << "Draka" << endl;}; };
class A :public C {
int o;
int a;
public:
A() {cout << "Buduje C ";}
~A() {cout << "~F " << endl;} };
class D :public A {
float f; public:
D() {cout << "Buduje D";}
virtual void a() {cout << "Pośrednik" << endl;}
~D() {cout << "~E" << endl;} };
class B :public D {
short s;
int b; public:
B() {cout << "Buduje E ";}
~B() {cout << "~G" << endl;} };
class E :public B {
E() {cout << "Buduje B";}
~E() {cout << "~I" << endl;} };
class F :public G, public D { public:
F() {cout << "Buduje F ";}
void a() {cout << "Nieznany " << endl;}
void b() {}
~F() {cout << "~H" << endl;} };
void nic() {cout << endl;}
int main() {
C*a = new B();
nic();
a->b();
D*d = new F;
nic();
d->b();
d->a();
((G*)d) -> a();
delete d;
delete a;
return 0; }

about ctors and inheritance

Im kinda new to C++.
I have an assignment where I should implement c class' default ctor and cctor so that theyll print "c::ctor" and "c::cctor" respectively.
I have no idea of how to deal with this, help would be appreciated.
#include <iostream>
#include <string>
using namespace std;
class a {
public:
a(const char* sname)
: _sname(sname) {
cout << "a::ctor" << endl;
}
a(const a& s) { cout << "a::copy ctor" << endl; }
virtual ~a() { cout << "a::dtor " << endl; }
void f1() { cout << "a::f1()" << endl; f2(); }
virtual void f2() = 0;
private:
string _sname;
};
class b1 : virtual public a {
public:
b1(const char* saname, const char* ssname)
: _sname1(saname), a(ssname) {
}
b1(const b1& b1) : a(b1) { cout << "b1 :: copy ctor << endl"; }
~b1() { cout << "b1::dtor" << endl; }
virtual void f1() { cout << "b1::f1()" << endl; }
virtual void f2() { cout << "b1::f2()" << endl; }
virtual void f3() { cout << "b1::f3()" << endl; }
private:
string _sname1;
};
class b2 : virtual public a {
public:
b2(const char* saname, const char* ssname)
: _sname2(saname), a(ssname) {
cout << "b2::ctor" << endl;
}
b2(const b2& b2) : a(b2) { cout << "b2::copy ctor" << endl; }
~b2() { cout << "b2::dtor" << endl; }
virtual void f3() { f1(); cout << "b2::f3()" << endl; }
private:
string _sname2;
};
class c : public b1, public b2 {
public:
c();
c(const c& c);
~c() { cout << "c::dtor" << endl; }
virtual void f1() { a::f1(); cout << "c::f1()" << endl; }
void f3() { cout << "c::f3()" << endl; }
};
In case of virtual inheritance, things are more complicated for the constructors and destructors. The constructors and the destructors of the virtual base class a should also be called in the c class since the compiler cannot choose between b1 or b2 to build the (unique) a part in the c object. For the destructor, the compilers handles things to call the destructor of b1, the destructor of b2 and the destructor of a.
So you should implement
class c : public b1, public b2 {
public:
c() : b1("", ""), b2("", ""), a("") {}
c(const c& src) : b1(src), b2(src), a(src) {}
};
In general, you should try to avoid virtual inheritance when not necessary. But it is a good exercise to understand how it works.

c++ dynamic_cast over decorator instantiations fails

I am trying to understand how decorator pattern works and how much I can "stretch" it to me needs. Following this example, I have extended classes XYZ. There exist derived classes "KLM" (from XYZ)
Specifically, even though I have a decorator pattern, the derived decorator classes "KLM" have some functionality that does not show up in any of their base classes "XYZ", "D", "I" or "A".
So while normally I would instantiate an object as
I * inKLM = new L( new M( new K( new A )));
This would not allow me to access the K::doVirtR() , L::doVirtS() and M::doVirtT() functions (see code below). To access these I would need to downcast the inKLM pointer using dynamic_cast to each of classes "KLM".
The problem is that I only manage to do this for the leftmost new in the expression above. I have read that polymorphism needs to be maintained in order for the dynamic casting to work, so I have tried to have a virtual destructor in all functions. Still I cannot get the dynamic cast to work for anything other than the "outer" new operation (in this case object of class "L").
Please see this code. How can I make not only "LinKLM" , but also "MinKLM" and "KinKLM" success in dynamic_casting ?
#include <iostream>
#include <list>
using namespace std;
class D; //decorator base
struct I { //interface (for both Base and DecoratorBase
I(){
cout << "\n| I::ctor ";
}
virtual ~I(){
cout << "I::dtor |" ;
}
virtual void do_it() = 0;
virtual void regDecorator(D* decorator) = 0;
virtual void train() = 0;
virtual void et() = 0;
};
class D: public I { //DecoratorBase : has same-named fns as Base (must be exported on I) and calls upon them.
public:
D(I * inner) : m_wrappee(inner) {
cout << "D::ctor ";
regDecorator(this);
}
virtual ~D() {
cout << "D::dtor ";
delete m_wrappee;
}
void do_it() {
m_wrappee->do_it();
}
virtual void et() {
cout << "filling in for lack of et() in derived class\n";
} //almost pure virtual, just not implemented in all derived classes
void train(){
m_wrappee->train();
}
private:
void regDecorator(D* decorator){
m_wrappee->regDecorator(decorator);
}
I * m_wrappee;
};
class A: public I { //Base has all the basic functionality
public:
A() {
cout << "A::ctor " ;
decList.clear();
}
~A() {
cout << "A::dtor |" ;
}
void do_it() {
cout << 'A';
}
void train(){
et();
}
void regDecorator(D* decorator)
{
if (decorator) {
cout << "reg=" << decorator << " ";
decList.push_back(decorator);
}
else
cout << "dec is null!" <<endl;
}
private:
void et()
{
//size_t counter=0;
list<D*>::iterator it;
for( it=decList.begin(); it != decList.end(); it++ )
{
//if ( (*it)->et() )
(*it)->et();
//else
// cout << "couldnt et cnt=" << counter << endl;
//counter++;
}
}
std::list<D*> decList;
};
class X: public D { //DerivedDecoratorX ..
public:
X(I *core): D(core){
cout << "X::ctor ";
}
virtual ~X() {
cout << "X::dtor ";
}
void do_it() {
D::do_it();
cout << 'X';
}
void doX() {
cout << "doX" << endl;
}
protected:
virtual void doVirtR() = 0;
private:
void et(){
cout << "X::et" <<endl;
}
};
class K: public X {
public:
K(I * core):X(core) {
cout << "K::ctor " ;
}
virtual ~K() {
cout << "K::dtor ";
}
void doVirtR(){
cout << "doVirtK" <<endl;
}
};
class Y: public D {
public:
Y(I *core): D(core){
cout << "Y::ctor ";
}
virtual ~Y() {
cout << "Y::dtor ";
}
/*void et(){
cout << "Y::et" <<endl;
}*/
void do_it() {
D::do_it();
cout << 'Y';
}
void doY() {
cout << "doY" << endl;
}
protected:
virtual void doVirtS() = 0;
};
class L: public Y{
public:
L(I * core):Y(core) {
cout << "L::ctor ";
}
virtual ~L() {
cout << "L::dtor ";
}
void doVirtS(){
cout << "doVirtL" <<endl;
}
};
class Z: public D {
public:
Z(I *core): D(core){
cout << "Z::ctor ";
}
virtual ~Z() {
cout << "Z::dtor ";
}
void et(){
cout << "Z::et" <<endl;
}
void do_it() {
D::do_it();
cout << 'Z';
}
void doZ() {
cout << "doZ" << endl;
}
virtual void doVirtT() = 0;
};
class M: public Z{
public:
M(I * core):Z(core) { //must add D(core) here explicitly because of virtual inheritance in M's base class (Z).
cout << "M::ctor " ;
}
virtual ~M() {
cout << "M::dtor ";
}
void doVirtT(){
cout << "doVirtM" <<endl;
}
};
int main(void) //testing dynamic casting
{
I * inKLM = new L( new M( new K( new A )));
L * LinKLM = dynamic_cast<L *>( inKLM);
M * MinKLM = dynamic_cast<M *>( inKLM);
K * KinKLM = dynamic_cast<K *>( inKLM);
cout << endl;
if ( ! MinKLM ) cout << "null MinKLM!" << endl;
if ( ! LinKLM ) cout << "null LinKLM!" << endl;
if ( ! KinKLM ) cout << "null KinKLM!" << endl;
//KinKLM->doVirtR();
//LinKLM->doVirtS();
//MinKLM->doVirtT();
//LinKLM->D::train();
//KinKLM->do_it();
//MinKLM->doZ();
delete inKLM;
cout << endl;
return 0;
}
If you need access to functionality that is unique in some of the inner classes, you may be better off (depending on the particular problem) trying mixin classes. The basic idea is to have a template class inherit its template parameter. I have simplified the classes below but the principle is clear:
#include <iostream>
// your base class
class I {
public:
virtual void do_it() {}
};
// a decorator
template <class Base>
class T1 : public Base {
public:
void do_it() {
std::cout << "T1" << std::endl;
Base::do_it();
}
void unique_in_T1() {
std::cout << "Unique in T1" << std::endl;
}
};
// another decorator
template <class Base>
class T2 : public Base {
public:
void do_it() {
std::cout << "T2" << std::endl;
Base::do_it();
}
void unique_in_T2() {
std::cout << "Unique in T2" << std::endl;
}
};
// yet another decorator
template <class Base>
class T3 : public Base {
public:
void do_it() {
std::cout << "T3" << std::endl;
Base::do_it();
}
void unique_in_T3() {
std::cout << "Unique in T3" << std::endl;
}
};
int main(int argc, const char * argv[]) {
T3<T2<T1<I>>> my_object1;
my_object1.do_it();
my_object1.unique_in_T2();
T1<T3<I>> my_object2;
my_object2.do_it();
my_object2.unique_in_T3();
return 0;
}
Your class D is not needed anymore. The main purpose of that class is to wrap the object that actually does the job while maintaining the interface of I. With mixin classes there is no wrapping anymore as it has been replaced by inheritance, hence there is no need for the D class.
Here is a link to read more.

C++ virtual destructor

The question is based on following class hierarchy.
Base2* d3 = new Der3();
d3->v1();
delete d3;
The output is :
Base1
Base1
Der1
Base2
Der3
v1 Base2
~Base2
And I get an exception.Why?(It only should generate memory leack)
class Base1
{
public:
Base1() {std::cout << "Base1" << std::endl; }
~Base1() {std::cout << "~Base1" << std::endl; }
virtual void v1() { std::cout << "v1 Base1" << std::endl; }
void v2() {std::cout << "v2 Base1" << std::endl;}
void v3() {std::cout << "v3 Base1" << std::endl;}
};
class Base2
{
public:
Base2() {std::cout << "Base2" << std::endl; }
~Base2() {std::cout << "~Base2" << std::endl; }
void v1() { std::cout << "v1 Base2" << std::endl; }
void v2() {std::cout << "v2 Base2" << std::endl;}
void v3() {std::cout << "v3 Base2" << std::endl;}
};
class Der1 : public Base1
{
public:
Der1() {std::cout << "Der1" << std::endl; }
~Der1() {std::cout << "~Der1" << std::endl; }
virtual void v1() { std::cout << "v1 Der1" << std::endl; }
virtual void v2() {std::cout << "v2 Der1" << std::endl;}
void v3() {std::cout << "v3 Der1" << std::endl;}
};
class Der2 : public Base1,public Der1
{
public:
Der2() {std::cout << "Der2" << std::endl; }
~Der2() {std::cout << "~Der2" << std::endl; }
virtual void v1() { std::cout << "v1 Der2" << std::endl; }
void v2() {std::cout << "v2 Der2" << std::endl;}
void v3() {std::cout << "v3 Der2" << std::endl;}
};
class Der3 : public Base1,public Der1,public Base2
{
public:
Der3() {std::cout << "Der3" << std::endl; }
~Der3() {std::cout << "~Der3" << std::endl; }
virtual void v1() { std::cout << "v1 Der3" << std::endl; }
void v2() {std::cout << "v2 Der3" << std::endl;}
void v3() {std::cout << "v3 Der3" << std::endl;}
};
Why do you say you should only get a memory leak? It's undefined behavior; anything can happen.
The problem is probably because the virtual destructor also serves to determine the deallocation function and the address to pass to it. In your case, you end up passing the wrong address to ::operator delete. But that's just what is probably happening in practice. It's undefined behavior, and anything can happen.
If you plan to derive from a class and use a pointer to a base class to delete the object, you must declare it's destructor virtual. Otherwise, it is undefined behavior.
class A
{
public:
~A() {}
...
};
class B : public A
{
public:
~B() {}
...
};
class C
{
public:
virtual ~C() {}
...
};
class D : public C
{
public:
virtual ~D() { }
...
};
B b; // OK, but bad practice
A* pa = new B; // not ok - when you try to delete
C* pc = new D; // ok