Policies/Binary Compatibility Examples

From KDE TechBase
Revision as of 08:31, 15 July 2009 by Thiago (talk | contribs) (Add a section on changing the type of global data)

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();

};