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

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; }

Related

Calling inherited functions and overriding behavior in c++

Why does this give this error -
'void D::func(const D &)': cannot convert argument 1 from 'const C' to 'const D &'
How to correct this, I want to call Base's func from Derived's func but note func is a friend function?
class C
{
public:
C()
{
cout << "in C ctor" << endl;
}
friend void func(const C& abc1)
{
cout << "in C's func" << endl;
}
};
class D : public C
{
public:
D()
{
cout << "in D ctor" << endl;
}
void func(const D& abc)
{
func(static_cast<const C&>(abc));
cout << "in D's func" << endl;
}
};
int main()
{
D d;
d.func(d);
}
why does this similar e.g. work though -
https://ideone.com/eNmvng
I'm not sure what that syntaxis does with function visibility, but this works:
class C
{
public:
C()
{
cout << "in C ctor" << endl;
}
friend void func(const C& abc1);
};
void func(const C& abc1)
{
cout << "in C's func" << endl;
}
class D : public C
{
public:
D()
{
cout << "in D ctor" << endl;
}
void func(const D& abc)
{
::func(abc);
cout << "in D's func" << endl;
}
};
int main()
{
D d;
d.func(d);
}
Just for completeness sake, this works too:
class C
{
public:
C()
{
cout << "in C ctor" << endl;
}
friend void func(const C& abc1)
{
cout << "in C's func" << endl;
}
};
// Make function visible in global scope
void func(const C& abc1);
class D : public C
{
public:
D()
{
cout << "in D ctor" << endl;
}
void func(const D& abc)
{
::func(abc);
cout << "in D's func" << endl;
}
};
int main()
{
D d;
d.func(d);
}

Using shared_from_this() with derived class

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>?

Inherited class's constructor is not running

I have 3 classes, A,B, and C.
Edited code.
#include <iostream>
class A {
public:
virtual void print() {
std::cout << "A" << std::endl;
}
A() : x(0) {} // constructor
void SetX (int tmp){
x = tmp;
}
void printX() {
std::cout << "x = " << x << std::endl;
}
private:
int x;
};
class B : public A {
public:
virtual void print(){
std::cout << "B" << std::endl;
}
B(int tmp) : A() {
SetX(tmp);
}
};
class C : public B {
public:
virtual void print(){
std::cout << "C" << std::endl;
}
C(int tmp) : B(tmp) {
std::cout << "Debug print" << std::endl;
}
};
int main() {
B* b = new B(1);
C* c = new C(2);
b->print();
b->printX();
c->print();
c->printX();
return 0;
}
print for b->printX = 1
and for c->printX = 0
when creating object B everything is work just fine.
but when creating object C the default value of class A (var x) is still 0 (default value).
i added debug line inside the constructor of class C, but i didnt see it in logs, looks like the constructor is not running. i did the same thing in the constructor of class B when creating only object C and i didnt see any debug print too.
There no any compiling error for this code. build finish successfully.
The following is legal and working C++. Your code was not legal C++.
I added a void printX() method to class A to illustrate the example.
#include <iostream>
class A {
public:
virtual void print() {
std::cout << "A" << std::endl;
}
A() : x(0) {} // constructor
void SetX (int tmp){
x = tmp;
}
void printX() {
std::cout << "x = " << x << std::endl;
}
private:
int x;
};
class B : public A {
public:
virtual void print(){
std::cout << "B" << std::endl;
}
B(int tmp) : A() {
SetX(tmp);
}
};
class C : public B {
public:
virtual void print(){
std::cout << "C" << std::endl;
}
C(int tmp) : B(tmp) {
std::cout << "Debug print" << std::endl;
}
};
int main() {
B* b = new B(1);
C* c = new C(2);
b->print();
b->printX();
c->print();
c->printX();
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++ 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