2016-02-10 5 views
0

Предположим, у меня есть библиотека, которую я хочу скрыть. В этой библиотеке есть функция называется «весело»C++ pimpl avoiding void *

//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); 
} 

Благодарности

+0

Если 'fun' - это функция, не являющаяся членом, которая работает только с общими интерфейсами' class1' и 'class2', вам необходимо убедиться, что версии' pimpl' также поддерживают эти интерфейсы. –

+0

Кроме того, использование 'unique_ptr' с не устраняет необходимость в определении конструктора копирования и оператора присваивания копий. –

+0

Непонятно, где находится проб. Вы получаете какие-либо ошибки компилятора? –

ответ

0

Вы предполагаете, что функции в 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*).

0

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

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

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

На стороне примечания, действительно ли fun_simple нужна копия class1? Если нет, это должно быть ссылка на const. Тем более, что копирование класса с помощью pimpl связано с распределением, а распределение довольно медленное.