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