Статическая библиотека: скрытие закрытых элементов из заголовочного файла

Я хочу скомпилировать часть своего кода в виде статической библиотеки для включения в другой проект. Конечно, мне придется распространять скомпилированную библиотеку и заголовочный файл, содержащий объявление класса и общедоступные члены, но я не знаю, возможно ли переместить все частные члены и объявления в место, отличное от заголовочного файла.

Пример:

В файле project.h:

class MyClass
{
public: 
  MyClass();
  void Give_me_an_input(int);
  int Get_your_output();

private:
  int a, b;
  int MySecretAlgorithm();
};

В файле .cpp:

MyClass::MyClass()
{
  a = 1; 
  b = 0;
}

void MyClass::Give_me_an_input(int c)
{
  b = c;
}

int MyClass::Get_your_output()
{
  return MySecretAlgorithm();
}

int MyClass::MySecretAlgorithm()
{
  return (a + b);
}

Есть ли способ переместить все частные члены int a, b; и int MySecretAlgorithm(); в место, отличное от файла заголовка?


person Mark Miles    schedule 01.05.2014    source источник
comment
Нет, потому что они необходимы для определения класса. Но вы можете повторно реализовать класс, используя, например. идиома pimpl (за счет некоторой косвенности).   -  person juanchopanza    schedule 02.05.2014
comment
Вас волнует, что другие могут видеть только объявление? Вы можете объявить его каким-нибудь фиктивным бессмысленным именем. Затем в файле cpp реализуйте его. В вашем секретном файле создайте указатель на эту функцию со значимым именем   -  person SomethingSomething    schedule 02.05.2014
comment
если вы хотите скрыть информацию от тех, кто использует эту библиотеку, вы можете рассмотреть возможность использования чего-то вроде vector<void*> и приведения элементов по мере необходимости. Хотя это было бы некрасиво.   -  person Red Alert    schedule 02.05.2014
comment
+1 за идиому pimpl   -  person 101010    schedule 02.05.2014
comment
Почему вы хотите это сделать? Какова мотивация/цель?   -  person Arun    schedule 02.05.2014


Ответы (2)



На протяжении многих лет я видел некоторые хаки для этого, но я не думаю, что они того стоят. Если ваша библиотека достаточно "короткая" (т.е. ни один метод не вызывается миллиард раз в микросекунду); и вы можете переписать куски своего кода...

Вы можете подумать о том, чтобы сделать все общедоступные вещи абстрактным классом (все виртуальные = 0), а затем получить от него свои конкретные классы.

Минусы этого: - Все ваши публичные звонки становятся виртуальными (некоторые оптимизации могут обойти это, но не часто). - Вы больше не можете «обновлять» свои классы, вам нужно будет реализовать фабричный шаблон.

Проблема с любым другим хаком, с которым я знаком, заключается в том, что они в основном объявляют методы в одном наборе заголовков, а затем повторно объявляют те же самые вещи с «настоящей» реализацией в закрытых заголовках — в зависимости от компоновщика, чтобы сопоставить имена. Пара проблем здесь:

  • Хреново поддерживать этот бардак. Вы не можете использовать #ifdef, потому что это звучит так, как будто вы хотите физически скрыть свою реализацию. Таким образом, у вас есть двойное обслуживание или шаг сборки, который генерирует ваши общедоступные заголовки.

  • Может использоваться только через указатель. Вы должны играть в игры, делая конструкторы закрытыми, и при этом иметь фабрику, потому что компилятор не будет генерировать структуры нужного размера, если вы позволите клиенту генерировать его по значению (или даже с новым).

  • Наконец, однажды я видел хак, когда программист пытался объявить массив байтов в приватной области класса «общедоступный», чтобы клиентский код все еще мог объявить его по значению или «новому». Это страдает от всех предыдущих проблем, плюс вы, вероятно, не хотите «знать» размер структур, поскольку они зависят от упаковки и выравнивания. Ваш «шаг сборки» более или менее должен иметь компонент времени выполнения, который использует sizeof(), и теперь у вас есть проблема с версиями, если вы хотите изменить размер структуры/класса.

person Joe    schedule 01.05.2014