Policies/Binary Compatibility Examples: Difference between revisions

From KDE TechBase
(Undo revision 43255: oops, this example was already there)
(Add a section on changing CV qualifiers of data)
Line 232: Line 232:
|}
|}


== Change the CV-qualifiers ==
== Change the CV-qualifiers of a member function ==
{|
{|
|-
|-
Line 250: Line 250:
public:
public:
     int something();
     int something();
};
</code>
|}
== Change the CV-qualifiers of global data ==
{|
|-
! Before
! After
|-
| <code cppqt>
// MSVC mangling: ?data@@3HA
int data = 42;
</code>
| <code cppqt>
// MSVC mangling: ?data@@3HB
const int data = 42;
</code>
|-
| <code cppqt>
class MyClass
{
public:
    // MSVC mangling: ?data@MyClass@@2HA
    static int data;
};
</code>
| <code cppqt>
class MyClass
{
public:
    // MSVC mangling: ?data@MyClass@@2HB
    static const int data;
};
</code>
|-
| <code cppqt>
class MyClass
{
public:
    static int data;
};
</code>
| <code cppqt>
class MyClass
{
public:
    // the compiler won't even create a symbol
    static const int data = 42;
};
};
</code>
</code>

Revision as of 08:28, 15 July 2009

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

};