Files
qt5-legatus-legacy/Lts/Viewer/SituationMap/UnitTests/virtual_inheritances.cpp
T
2026-08-13 18:33:10 +02:00

253 lines
5.1 KiB
C++
Executable File

/**
* @RDE_HEADER@
* Unittest
* $Id$
* $HeadURL$
* $Author$
*/
#include "unit_test.h"
#include <QCoreApplication>
#include <QtTest/QTest>
#include <QtTest/QSignalSpy>
#include <NGLLogger/NGLLoggerBootstrap.h>
#include <iostream>
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* 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.");
}
//-------------------------------------------------------------------------------------------------------