C++ pimpl избегая пустоты *
Предположим, у меня есть библиотека, которую я хочу скрыть. В этой библиотеке есть функция, которая называется "весело"
//Both class1 and class2 are defined in the library I want to hide
class1 fun(class2 P)
Я сейчас создаю pimpl для class1 и class2.Как мне реализовать функцию "веселье"? Код для class1_pimpl и class2_pimpl ниже
//class1_pimpl.hpp
class class1_pimpl
{
public:
class1_pimpl(int value);
~class1_pimpl();
private:
class Impl;
std::unique_ptr<Impl> pimpl_;
};
//class2_pimpl.hpp
class class2_pimpl
{
public:
class2_pimpl(int value);
~class2_pimpl();
private:
class Impl;
std::unique_ptr<Impl> pimpl_;
};
Я могу только выяснить, если функция относится только к одному классу, например,
int fun_simple(class1 c, int i)
Как я решаю fun_simple, как показано ниже:
//class1_pimpl.cpp
class class1_pimpl::Impl
{
public:
Impl(int value)
: value_ {value}
{}
int fun_simple(i)
{
return value_ + i;
}
private:
int value_;
};
class1_pimpl::class1_pimpl(int value)
: pimpl_{new Impl(value)}
{}
class1_pimpl::~class1_pimpl()
{}
int class1_pimpl::fun_simple(int i)
{
return pimpl_->fun_simple(i);
}
Спасибо
2 ответа
Вы предполагаете, что функции в C++ должны быть функциями-членами. Это ясно из вашей "реализации" int fun_simple(class1 c, int i)
как int class1_pimpl::fun_simple(i)
, Там нет необходимости в этом. C++ имеет бесплатные функции. int fun_simple(class1 c, int i)
это идеальное определение как есть.
Одна вещь, которую вы хотите изменить, это int fun_simple(class1 const&c, int i)
, Это означает, что класс не нужно копировать. В свою очередь, вам не нужно иметь доступ к конструктору копирования. А это значит, что вы можете просто объявить class1;
, Вам даже не нужно pimpl
за это! Вместо этого в своем заголовке вы просто предоставляете std::unique_ptr<class1> makeClass1(/* your args*)
,
В большинстве случаев функция должна создать возвращаемое значение, используя открытый конструктор. Тогда вам не требуется повышенный доступ к этому классу, и вы либо делегируете его члену, либо делаете его первым.
Если классы настолько связаны между собой, что использование частного конструктора предпочтительнее, вы всегда можете сделать функцию другом class2
,
Чтобы избежать необходимости определения class2_pimpl
создать частный конструктор в class2
это позаботится о его создании и заполнении. Выполнение в конструкторе будет более надежным в любом случае.
На заметку, действительно ли fun_simple нужна копия class1
? Если нет, то следует обратиться к константной ссылке. Тем более, что копирование класса с помощью pimpl предполагает выделение, а выделение происходит довольно медленно.