This page is meant as examples of things you cannot do in C++ when maintaining binary compatibility.
Unexport or remove a class
Before
|
After
|
class KDECORE_EXPORT KUrl
{
// [...]
};
|
class KUrl
{
// [...]
};
|
Change the class hierarchy
Before
|
After
|
class MyClass: public BaseClass
{
// [...]
};
|
class MyClass: public BaseClass, public OtherBaseClass
{
// [...]
};
|
class MyClass: public BaseClass1, public BaseClass2
{
// [...]
};
|
class MyClass: public BaseClass2, public BaseClass1
{
// [...]
};
|
Change the template arguments of a template class
Before
|
After
|
template<typename T1>
class MyTemplateClass
{
// [...]
};
|
template<typename T1, typename T2 = void>
class MyTemplateClass
{
// [...]
};
|
Unexport a function
Before
|
After
|
Q_CORE_EXPORT const char *qVersion();
|
const char *qVersion();
|
namespace KSocketFactory {
KDECORE_EXPORT QTcpSocket *connectToHost(...);
}
|
namespace KSocketFactory {
QTcpSocket *connectToHost(...);
}
|
Inline a function
Before
|
After
|
int square(int n);
|
inline int square(int n) { return n * n; }
|
int square(int n) { return n * n; }
|
inline int square(int n) { return n * n; }
|
class Math
{
int square(int n);
};
// the following could be in a .cpp
int Math::square(int n)
{ return n * n; }
|
class Math
{
int square(int n);
};
// the following could be in a .cpp
inline int Math::square(int n)
{ return n * n; }
|
class Math
{
int square(int n);
};
// the following could be in a .cpp
int Math::square(int n)
{ return n * n; }
|
class Math
{
int square(int n)
{ return n * n; }
};
|
Change the parameters of a function
Before
|
After
|
void doSomething(int i1, int i2);
|
void doSomething(int i1, short i2);
|
void doSomething(int i1, int i2);
|
void doSomething(int i1, int i2, int i3 = 0);
|
void doSomething(int i1);
|
void doSomething(const int i1); // breaks with MSVC and Sun CC
|
void doSomething(char *ptr);
|
void doSomething(const char *ptr);
|
Change the return type
Before
|
After
|
QTcpSocket *createDevice();
|
QIODevice *createDevice();
|
Change the access rights
Before
|
After
|
class MyClass
{
protected:
void doSomething();
};
|
class MyClass
{
public:
void doSomething();
};
|
Change the CV-qualifiers of a member function
Before
|
After
|
class MyClass
{
public:
int something() const;
};
|
class MyClass
{
public:
int something();
};
|
Change the type of global data
Before
|
After
|
// MSVC mangling: ?data@@3HA
int data = 42;
|
// MSVC mangling: ?data@@3FA
short data = 42;
|
class MyClass
{
public:
// MSVC mangling: ?data@MyClass@@2HA
static int data;
};
|
class MyClass
{
public:
// MSVC mangling: ?data@MyClass@@2FA
static short data;
};
|
Change the CV-qualifiers of global data
Before
|
After
|
// MSVC mangling: ?data@@3HA
int data = 42;
|
// MSVC mangling: ?data@@3HB
const int data = 42;
|
class MyClass
{
public:
// MSVC mangling: ?data@MyClass@@2HA
static int data;
};
|
class MyClass
{
public:
// MSVC mangling: ?data@MyClass@@2HB
static const int data;
};
|
class MyClass
{
public:
static int data;
};
|
class MyClass
{
public:
// the compiler won't even create a symbol
static const int data = 42;
};
|
Add a virtual member function to a class without any
Before
|
After
|
struct Data
{
int i;
};
|
struct Data
{
int i;
virtual int j();
};
|
Add new virtuals to a non-leaf class
Before
|
After
|
class MyClass
{
public:
virtual ~MyClass();
virtual void foo();
};
|
class MyClass
{
public:
virtual ~MyClass();
virtual void foo();
virtual void bar();
};
|
Change the order of the declaration of virtual functions
Before
|
After
|
class MyClass
{
public:
virtual ~MyClass();
virtual void foo();
virtual void bar();
};
|
class MyClass
{
public:
virtual ~MyClass();
virtual void bar();
virtual void foo();
};
|
Override a virtual that doesn't come from a primary base
class PrimaryBase
{
public:
virtual ~PrimaryBase();
virtual void foo();
};
class SecondaryBase
{
public:
virtual ~PrimaryBase();
virtual void bar();
};
Before
|
After
|
class MyClass: public PrimaryBase, public SecondaryBase
{
public:
~MyClass();
void foo();
};
|
class MyClass: public PrimaryBase, public SecondaryBase
{
public:
~MyClass();
void foo();
void bar();
};
|
Override a virtual with a covariant return with different top address
struct Data1 { int i; };
class BaseClass
{
public:
virtual Data1 *get();
};
struct Data0 { int i; };
struct Complex1: Data0, Data1 { };
struct Complex2: virtual Data1 { };
Before
|
After
|
class MyClass: public BaseClass
{
public:
};
|
class MyClass: public BaseClass
{
public:
Complex1 *get();
};
|
class MyClass: public BaseClass
{
public:
};
|
class MyClass: public BaseClass
{
public:
Complex2 *get();
};
|