Policies/Binary Compatibility Examples

From KDE TechBase
Revision as of 08:28, 15 July 2009 by Thiago (talk | contribs) (Add a section on changing CV qualifiers of data)
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

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

};