Оболочка класса C++ для структуры C
Я хочу написать класс c++, который обертывает структуру c. Вот простой пример для структуры c:
struct POINT {
long x;
long y;
}
Теперь я предполагаю, что это следующий класс, но я не уверен, является ли он "performant" или хорошим стилем c++. Я не хотел использовать ненужную переменную или вызов функции. Было бы очень хорошо, если бы вы улучшили мой код :).
Основная идея этого класса заключается в том, что он является всего лишь оболочкой/ обработчиком для структуры. Вот почемуsetStruct
и getStruct
могут изменять личные данные прямо и что это просто указатель. Остальные члены всегда называются set<Attribute>
и get<Attribute>
.
Если вы используете setStruct
Единственный недостаток, который я могу придумать, это то, что структура может быть удалена из-за областей, так что указатель "недействителен".
namespace wrapper {
class POINT {
::POINT * POINT_;
public:
POINT() {
POINT_ = new ::POINT;
}
~POINT() {
delete POINT_;
}
inline void setX( long x ) {
POINT_->x = x;
}
inline long getX() {
return POINT_->x;
}
inline void setY( long y ) {
POINT_->y = y;
}
inline long getY() {
return POINT_->y;
}
inline void setStruct(::POINT * __POINT) {
POINT_ = __POINT;
}
inline ::POINT * getStruct() {
return POINT_;
}
};
}
2 ответа:
В этом случае вам, возможно, лучше использовать наследование вместо композиции. Это избавит вас от необходимости управлять дополнительным ресурсом и позволит вашей "оболочке" действовать как точка вместо того, чтобы требовать доступов и мутаторов для всей структуры точки.
namespace wrapper { class Point : public ::POINT { public: Point() { } ~Point() { } // The following accessors/mutators may not be necessary. // They can however be handy with code that requires a pointer to // member function (i.e. transformations) void setX(long nx) { x = nx; } long getX() { return x; } void setY(long ny) { y = ny; } long getY() { return y; } // copy assignment operators Point& operator=(const POINT& p) { x = p.x; y = p.y; return *this; } Point& operator=(const Point& p) { x = p.x; y = p.y; return *this; } }; }
Если вы хотите предотвратить прямой доступ к членам
POINT
, Вы можете использовать частное наследование. Вы также можете предоставить оператор преобразования, чтобы разрешить неявные преобразования изPoint
вPOINT
. Это заменитPOINT* getStruct()
функция-член, но все же позволяет легко использовать ее с функциями, которые требуютPOINT
в качестве аргумента.namespace wrapper { // Use private inheritance to prevent direct access to the // members of POINT class Point : private POINT { public: Point() { } ~Point() { } // Copy constructor Point(const ::POINT& p) { x = p.x; y = p.y; } // Accessor/mutators void setX(long nx) { x = nx; } long getX() { return x; } void setY(long ny) { y = ny; } long getY() { return y; } // Allow implicit conversions to POINT* when necessary // Replaces getStruct() operator ::POINT*() { return this; } operator const ::POINT*() const { return this; } // Copy assignment operators Point& operator=(const POINT& p) { x = p.x; y = p.y; return *this; } Point& operator=(const Point& p) { x = p.x; y = p.y; return *this; } }; } extern "C" void someCFunction(POINT *); int main() { POINT cp; wrapper::Point p; p.x = 0; // FAIL p.setX(0); // OK p = cp; // OK // No need to call getPoint(). someCFunction(p); }
примечание: Я удалил использование
inline
, поскольку они не нужны. Функции, определенные в определении класса, уже встроены (см. $7.1.2 / 3). Спасибо Крису за напоминание.
Как уже отмечалось,
_POINT
является зарезервированным именем, поскольку оно начинается с_
+ заглавной буквы.Использование всех заглавных букв для имен типов субъективно, хотя я склонен избегать этого.
Ваш класс будет иметь всевозможные проблемы (двойное удаление, удаление памяти без кучи и т. д.), Если вы когда-либо скопируете его или передадите адрес стековой точки в
setStruct
.Ваш класс будет намного проще и менее подвержен ошибкам, если вы просто составляете по значению. Вы сохраняете уровень косвенное обращение в обмен на копирование немного большего количества данных, но есть вероятность, что копия будет лучше сохранена в кэше, чем косвенное обращение, которое может дважды попасть в память.
Нет никакой реальной проблемы с наличием функций
getStruct
иsetStruct
для явного перевода в структуру C и из нее.Однако вот мой вопрос: Что дает вам ваша оболочка C++, чего не дает C-struct? Вы просто предоставляете обернутые методы отдельным атрибутам в любом случае, а не какой-то вид интерфейс, выполняющий другие операции над классом. В этом случае я вообще не вижу смысла использовать оболочку (если только вы не планируете добавить логику отладки к геттерам и сеттерам, чтобы вам было легче следить за потоком программы).