Skip to content

Instantly share code, notes, and snippets.

@jefferton
Last active January 11, 2018 05:09
Show Gist options
  • Save jefferton/60a46ec014344ca04e96648535498a27 to your computer and use it in GitHub Desktop.
Save jefferton/60a46ec014344ca04e96648535498a27 to your computer and use it in GitHub Desktop.
Compares the effect of delete-ing objects via base class pointer when the base class and/or child class lacks a virtual destructor
// Compares the effect of delete-ing objects via base class pointer
// when the base class and/or child class lacks a virtual destructor
#include <iostream>
#include <memory>
struct BaseMember
{
BaseMember() { std::cout << "BaseMember()\n"; }
~BaseMember() { std::cout << "~BaseMember()\n"; }
};
struct ChildMember
{
ChildMember() { std::cout << "ChildMember()\n"; }
~ChildMember() { std::cout << "~ChildMember()\n"; }
};
struct NonVirtual // <-------- NON-VIRTUAL DESTRUCTOR
{
NonVirtual() { std::cout << "NonVirtual()\n"; }
~NonVirtual() { std::cout << "~NonVirtual()\n"; }
BaseMember bm;
};
struct NonVirtualWithVirtualDestructor : NonVirtual
{
NonVirtualWithVirtualDestructor() { std::cout << "NonVirtualWithVirtualDestructor()\n"; }
virtual ~NonVirtualWithVirtualDestructor() { std::cout << "~NonVirtualWithVirtualDestructor()\n"; }
ChildMember cm;
};
struct NonVirtualWithNonVirtualDestructor : NonVirtual
{
NonVirtualWithNonVirtualDestructor() { std::cout << "NonVirtualWithNonVirtualDestructor()\n"; }
~NonVirtualWithNonVirtualDestructor() { std::cout << "~NonVirtualWithNonVirtualDestructor()\n"; }
ChildMember cm;
};
struct Virtual // <-------- VIRTUAL DESTRUCTOR
{
Virtual() { std::cout << "Virtual()\n"; }
virtual ~Virtual() { std::cout << "~Virtual()\n"; }
BaseMember bm;
};
struct VirtualWithVirtualDestructor : Virtual
{
VirtualWithVirtualDestructor() { std::cout << "VirtualWithVirtualDestructor()\n"; }
virtual ~VirtualWithVirtualDestructor() { std::cout << "~VirtualWithVirtualDestructor()\n"; }
ChildMember cm;
};
struct VirtualWithNonVirtualDestructor : Virtual
{
VirtualWithNonVirtualDestructor() { std::cout << "VirtualWithNonVirtualDestructor()\n"; }
~VirtualWithNonVirtualDestructor() { std::cout << "~VirtualWithNonVirtualDestructor()\n"; }
ChildMember cm;
};
struct PureVirtual // <-------- PURE VIRTUAL DESTRUCTOR
{
PureVirtual() { std::cout << "PureVirtual()\n"; }
virtual ~PureVirtual() = 0;
BaseMember bm;
};
PureVirtual::~PureVirtual() { std::cout << "~PureVirtual()\n"; }
struct PureVirtualWithVirtualDestructor : PureVirtual
{
PureVirtualWithVirtualDestructor() { std::cout << "PureVirtualWithVirtualDestructor()\n"; }
virtual ~PureVirtualWithVirtualDestructor() { std::cout << "~PureVirtualWithVirtualDestructor()\n"; }
ChildMember cm;
};
struct PureVirtualWithNonVirtualDestructor : PureVirtual
{
PureVirtualWithNonVirtualDestructor() { std::cout << "PureVirtualWithNonVirtualDestructor()\n"; }
~PureVirtualWithNonVirtualDestructor() { std::cout << "~PureVirtualWithNonVirtualDestructor()\n"; }
ChildMember cm;
};
struct DefaultVirtual // <-------- DEFAULT VIRTUAL DESTRUCTOR
{
DefaultVirtual() = default;
virtual ~DefaultVirtual() = default;
BaseMember bm;
};
struct DefaultVirtualWithVirtualDestructor : DefaultVirtual
{
DefaultVirtualWithVirtualDestructor() { std::cout << "DefaultVirtualWithVirtualDestructor()\n"; }
virtual ~DefaultVirtualWithVirtualDestructor() { std::cout << "~DefaultVirtualWithVirtualDestructor()\n"; }
ChildMember cm;
};
struct DefaultVirtualWithNonVirtualDestructor : DefaultVirtual
{
DefaultVirtualWithNonVirtualDestructor() { std::cout << "DefaultVirtualWithNonVirtualDestructor()\n"; }
~DefaultVirtualWithNonVirtualDestructor() { std::cout << "~DefaultVirtualWithNonVirtualDestructor()\n"; }
ChildMember cm;
};
struct EmptyVirtual // <-------- EMPTY VIRTUAL DESTRUCTOR
{
EmptyVirtual() {}
virtual ~EmptyVirtual() {}
BaseMember bm;
};
struct EmptyVirtualWithVirtualDestructor : EmptyVirtual
{
EmptyVirtualWithVirtualDestructor() { std::cout << "EmptyVirtualWithVirtualDestructor()\n"; }
virtual ~EmptyVirtualWithVirtualDestructor() { std::cout << "~EmptyVirtualWithVirtualDestructor()\n"; }
ChildMember cm;
};
struct EmptyVirtualWithNonVirtualDestructor : EmptyVirtual
{
EmptyVirtualWithNonVirtualDestructor() { std::cout << "EmptyVirtualWithNonVirtualDestructor()\n"; }
~EmptyVirtualWithNonVirtualDestructor() { std::cout << "~EmptyVirtualWithNonVirtualDestructor()\n"; }
ChildMember cm;
};
int main()
{
std::cout << "-------- GOOD -----------------\n";
{
std::unique_ptr<Virtual> bcp(new VirtualWithVirtualDestructor());
}
std::cout << "-------- GOOD -----------------\n";
{
std::unique_ptr<Virtual> bcp(new VirtualWithNonVirtualDestructor());
}
std::cout << "-------- GOOD -----------------\n";
{
std::unique_ptr<PureVirtual> bcp(new PureVirtualWithVirtualDestructor());
}
std::cout << "-------- GOOD -----------------\n";
{
std::unique_ptr<PureVirtual> bcp(new PureVirtualWithNonVirtualDestructor());
}
std::cout << "-------- GOOD -----------------\n";
{
std::unique_ptr<DefaultVirtual> bcp(new DefaultVirtualWithVirtualDestructor());
}
std::cout << "-------- GOOD -----------------\n";
{
std::unique_ptr<DefaultVirtual> bcp(new DefaultVirtualWithNonVirtualDestructor());
}
std::cout << "-------- GOOD -----------------\n";
{
std::unique_ptr<EmptyVirtual> bcp(new EmptyVirtualWithVirtualDestructor());
}
std::cout << "-------- GOOD -----------------\n";
{
std::unique_ptr<EmptyVirtual> bcp(new EmptyVirtualWithNonVirtualDestructor());
}
std::cout << "-------- BAD -----------------\n";
{
std::unique_ptr<NonVirtual> bcp(new NonVirtualWithNonVirtualDestructor());
}
std::cout << "-------- CRASH -----------------\n";
{
std::unique_ptr<NonVirtual> bcp(new NonVirtualWithVirtualDestructor());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment