/** * @RDE_HEADER@ * Unittest * $Id$ * $HeadURL$ * $Author$ */ #include "unit_test.h" #include #include #include #include #include /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * Test of virtual inheritance combined with constuctor delegation. With gcc all works fine. With Visual Studio 2013 on Windows * the constructor of VirtualBaseInterface class is called twice. This may crash the program or result in other unexpected behaviour. * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ class VirtualBaseInterface { public: static unsigned int _ctorCount; VirtualBaseInterface() { qDebug() << "ctor of class VirtualBaseInterface() has been called"; _ctorCount++; } VirtualBaseInterface(int, int) { // in case of virtual inheritance this ctor will never be used. qDebug() << "ctor of class VirtualBaseInterface(int x, int y) has been called"; _ctorCount++; } ~VirtualBaseInterface() = default; virtual void foo() = 0; }; unsigned int VirtualBaseInterface::_ctorCount = 0; class BaseClass : virtual public VirtualBaseInterface , public QObject { protected: int c; public: BaseClass(int x, int y) : BaseClass(x, y, 10) { qDebug() << "ctor of class BaseClass(int x,int y) has been called"; } BaseClass(int x, int y, int z) : VirtualBaseInterface(), QObject(), c(z) { Q_UNUSED(x) Q_UNUSED(y) qDebug() << "ctor of class BaseClass(int x,int y,int z) has been called"; } virtual ~BaseClass() = default; void foo() override { c = 10; } }; class Derived1 : public BaseClass { protected: int d; public: Derived1(int x, int y) : BaseClass(x, y), d(10) {} Derived1(int x, int y, int z, int w) : BaseClass(x, y, z), d(w) {} void foo() override { d = 13; } }; class Derived2 : public Derived1 { public: Derived2(int x, int y) : Derived1(x, y) {} Derived2(int x, int y, int z, int w) : Derived1(x, y, z, w) {} void foo() override { d = 17; } }; void SitMapUnitTest::virtualInheritances() { bool ok = true; qDebug() << endl << "Check Derived2(int x,int y,int z,int w)" << endl; try { Derived2 d(1, 2, 3, 4); d.foo(); } catch (...) { ok = false; } QVERIFY2(ok, "virtualInheritances for Derived2(int x,int y,int z,int w) failed."); qDebug() << endl << "Check Derived2(int x,int y)" << endl; try { Derived2 d(1, 2); d.foo(); } catch (...) { ok = false; } QVERIFY2(ok, "virtualInheritances for Derived2(int x,int y) failed."); QVERIFY2(VirtualBaseInterface::_ctorCount >= 2, "Too few calles of VirtualBaseInterface ctor."); QVERIFY2(VirtualBaseInterface::_ctorCount <= 2, "VirtualBaseInterface ctor has been called too often."); } // SitMapUnitTest::virtualInheritances class Referenced { public: Referenced() { _refCount++; } ~Referenced() = default; unsigned int refcount() { return _refCount; } static unsigned int _refCount; }; unsigned int Referenced::_refCount = 0; class AbstractInterface : public virtual Referenced { public: AbstractInterface() = default; ~AbstractInterface() = default; virtual void foo() = 0; }; class AbstractInterfaceImpl : public virtual AbstractInterface { unsigned int _data; public: AbstractInterfaceImpl() : AbstractInterface() { _data = 42; } ~AbstractInterfaceImpl() { _data = 0; } void foo() override; }; class ObjectInterface : public virtual AbstractInterface { public: // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Using the default constructor here like // ObjectInterface() = default; // gives a crash!!!! // Implementing the ctor works. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ObjectInterface() : AbstractInterface() {;} ~ObjectInterface() = default; virtual void foo2() = 0; }; class ObjectInterfaceImpl : public AbstractInterfaceImpl, public virtual ObjectInterface { unsigned int _objData; public: explicit ObjectInterfaceImpl(unsigned int data = 7) : ObjectInterface(), AbstractInterfaceImpl() { _objData = data; } ~ObjectInterfaceImpl() { _objData = 0; } void foo2() override; }; void AbstractInterfaceImpl::foo() { _data = 4711; } void ObjectInterfaceImpl::foo2() { _objData = 815; } void SitMapUnitTest::multiInheritancesVisualStudio2015Bug() { Referenced::_refCount = 0; bool ok = true; qDebug() << endl << "Check ctor ObjectInterfaceImpl " << endl; try { ObjectInterfaceImpl obj; obj.foo(); if (obj.refcount() != 1) ok = false; } catch (...) { ok = false; } QVERIFY2(ok, "Check ctor ObjectInterfaceImpl failed."); } //-------------------------------------------------------------------------------------------------------