C ++ обернуть C struct * и * и функции - PullRequest
3 голосов
/ 22 августа 2011

Я пытаюсь обернуть библиотеку C, в которой используются такие шаблоны:

Thing* x= new_thing_("blah");
Thing* tmp= thing_copy(x);
free_thing(tmp);
Other* y=get_other(x,7);
char* message=get_message(x,y);
free_thing(x);
free_other(y);

В C ++ я бы хотел иметь возможность сделать что-то вроде

auto_ptr<CXXThing> x=new CXXThing("blah");
auto_ptr<CXXThing> tmp=new CXXThing(*x);
auto_ptr<CXXOther> y=x->get_other(7);
char* message = y->get_message();

Очевидно, что CXXOther также переносит указатель на CXXThing.Поэтому проблема, с которой я сталкиваюсь, заключается в том, что по сути я хотел бы просто «вставить» функции и элементы в существующие структуры (я думаю, это известно как идея «Mixin»).

Проблема в том, что еслиЯ включаю Thing как элемент CXXThing, тогда я не знаю, как бы я объявил конструктор, и если я добавлю указатель на обернутый класс, то у меня будет дополнительный уровень бесполезногокосвенное.

Как мне обернуть его, чтобы это было возможно?(Ответ «То, что вы хотите сделать, не самый лучший / возможный ... вот правильный путь» также приемлем.)

1 Ответ

9 голосов
/ 22 августа 2011

Вместо использования auto_ptr s, вы можете использовать идиому RAII более напрямую.Вот один из способов сделать это:

A CXXThing класс, который охватывает Thing:

class CXXThing
{
public:
    // Acquire a Thing
    explicit CXXThing(const char* str) : x(::new_thing_(str)) {}
    // Copy a Thing
    CXXThing(const CXXThing& rhs) : x(::thing_copy(rhs.x)) {}
    // Copy-and-swap idiom
    CXXThing& operator=(CXXThing rhs)
    {
        swap(*this, rhs);
        return *this;
    }
    // Release a Thing
    ~CXXThing() { ::free_thing(x); }

    friend void swap(CXXThing& lhs, CXXThing& rhs)
    {
        Thing* tmp = lhs.x;
        lhs.x = rhs.x;
        rhs.x = tmp;
    }

private:
    Thing* x;
    friend class CXXOther;
};

A CXXOther класс, который охватывает Other:

class CXXOther
{
public:
    // Acquire an Other
    explicit CXXOther(CXXThing& thing, int i) : y(::get_other(thing.x, i)) {}
    // Release an Other
    ~CXXOther() { ::free_other(y); }
    // Get a message
    char* get_message(const CXXThing& x) { return ::get_message(x.x, y); }
private:
    // Instaces of Other are not copyable.
    CXXOther(const CXXOther& rhs);
    CXXOther& operator=(const CXXOther& rhs);
    Other* y; 
};

Перевод вашего кода C в код C ++ с помощью перечисленных выше классов:

int main()
{
    CXXThing x("blah");

    {
        CXXThing tmp = x;
    } // tmp will go away here.

    CXXOther y(x, 7);
    char* msg = y.get_message(x);
    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...