Поддержание ABI: добавление конструктора в структуру - PullRequest
2 голосов
/ 06 августа 2010

У нас есть структура в ревизии 1 разделяемой библиотеки, для которой нам нужно поддерживать ABI:

struct Person
{
    std::string first_name;
    std::string last_name;
}

В ревизии 2 мы меняем Person на это:

class Person
{
public:
    Person(const std::string &f, const std::string &l);

    std::string first_name;
    std::string last_name;
}

Чтобы обеспечить совместимость с исходным кодом, мы хотели бы изменить версию 1 Person так, чтобы код, скомпилированный с более новыми заголовочными файлами, запускался, а код, не перекомпилированный, запускался.

Можем ли мы сделать следующее с двумя новыми не встроенными конструкторами:

class Person
{
public:
    Person();
    Person(const std::string &f, const std::string &l);

    std::string first_name;
    std::string last_name;
}

Мы делаем все это с помощью g ++. Просматривая сгенерированную разделяемую библиотеку с помощью nm, я не вижу конструктора или деструктора для простой структуры, поэтому я предполагаю, что код, который не перекомпилируется, просто создаст Person на вызывающем сайте, как и раньше, что нормально. Любой перекомпилированный код будет использовать конструктор без аргументов.

Единственная проблема, которую я вижу, заключается в том, что если нам нужно откатиться к более старой версии разделяемой библиотеки, в которой нет конструкторов, тогда любой код, скомпилированный против нее, сломается, но я не беспокоюсь об этой ситуации.

Ответы [ 4 ]

3 голосов
/ 06 августа 2010

А как насчет следующего?

class NewPerson : public Person
{
public:
    NewPerson(const std::string &f, const std::string &l)
    {
      first_name = f;
      last_name = l;
    }
}
2 голосов
/ 06 августа 2010

Это может "сработать", но вы нарушите Правило Единого Определения, и, поскольку стандарт C ++ идет, вы окажетесь в стране неопределенного поведения, которая не является подходящим местом.

2 голосов
/ 06 августа 2010

Я думаю, что это должно работать, предполагая, что ваш явный ctor по умолчанию делает то же самое, что и ранее использовавшийся неявный ctor. В этом простом примере. Однако ИМХО трудно предсказать или знать, что будет делать / изменять компилятор. Я бы не стал доверять самому себе, я бы лучше перекомпилировал пользователей библиотеки, если бы вы были вами.

1 голос
/ 06 августа 2010

У вас не должно возникнуть проблем с добавлением новых не виртуальных функций в класс или структуру без нарушения бинарной совместимости. Это потому, что функция класса реализована как обычная функция, принимающая неявный this в качестве первого параметра.

Однако, если вы добавите новую виртуальную функцию, вы можете нарушить совместимость, поскольку новая функция приведет к изменению виртуальной таблицы, что может нарушить совместимость.

Таким образом, добавление дополнительных конструкторов (которые никогда не могут быть виртуальными) не нарушит совместимость. Если вы добавите виртуальный деструктор, вы, скорее всего, нарушите совместимость.

...