简体   繁体   English

当作为与结构相同类型的参数传递时,包装在 C++ 类中的 C 结构如何交互?

[英]How do C structs wrapped in C++ classes interact when passed as a parameter of the same type as the struct?

Say I have the code below using the WINDOW struct from NCurses.假设我使用 NCurses 的 WINDOW 结构有下面的代码。

#include "ncurses.h"

class Window : public WINDOW {
    Window(int winHeight, int winWidth, int startX, int startY) {
        newwin(winHeight, winWidth, startX, startY);
    }
    void refresh() {
        wrefresh(this);
    }
};

int main() {
    initscr();

    Window win = Window(5, 5, 5, 5);
    win.refresh();

    endwin();
    return 0;
}

Is there a proper way to have C++ classes inherit C structs so that they can be passed as them, similar to how C++ classes that have inherited each other can?是否有适当的方法让 C++ 类继承 C 结构,以便它们可以作为它们传递,类似于 C++ 类可以相互继承?

One way to create C++ 'wrappers' for structures defined in a C library, so that you can easily pass pointers to API calls in such a library is to emulate the way the MFC (Microsoft Foundation Class) library wraps GDI objects, such as the RECT structure, into classes like CRect . One way to create C++ 'wrappers' for structures defined in a C library, so that you can easily pass pointers to API calls in such a library is to emulate the way the MFC (Microsoft Foundation Class) library wraps GDI objects, such as the RECT结构,放入像CRect这样的类。

MFC uses straightforward inheritance of the 'base' structure, and provides operators in each class that return pointers to the base structure (which will actually be a class instance's this pointer). MFC uses straightforward inheritance of the 'base' structure, and provides operators in each class that return pointers to the base structure (which will actually be a class instance's this pointer).

In the code below, I show the definition of the RECT structure and some excerpts of the CRect class, from the relevant Windows headers and MFC headers/source.在下面的代码中,我显示了RECT结构的定义和CRect class 的一些摘录,来自相关的 Windows 标头和 MFC 标头/源。

// The "C" base structure, from "windef.h"
typedef struct tagRECT
{
    LONG    left;
    LONG    top;
    LONG    right;
    LONG    bottom;
} RECT, *LPRECT;

typedef const RECT *LPCRECT;
class CRect : public tagRECT
{
public:
    CRect(int l, int t, int r, int b) {
        // Assign given parameters to base structure members...
        left = l; top = t; right = r; bottom = b;
    }
//...
    // Utility routines...
    int Width() const {
        return right - left;
    }
//...
    // convert between CRect and LPRECT/LPCRECT (no need for &)
    operator LPRECT() {
        return this;
    }
    operator LPCRECT() const {
        return this;
    }
//...
};

With wrapper classes defined like this, you can pass a CRect object (as in the comment above, no need for & ) to a call from your C Library that expects a pointer to a RECT .使用这样定义的包装器类,您可以将CRect object (如上面的评论中,不需要& )传递给来自 C 库的调用,该调用需要指向RECT指针 For example, the GetWindowRect() function takes an LPRECT parameter and is called, from C, like this:例如, GetWindowRect() function采用LPRECT参数并从 C 调用,如下所示:

HWND hWnd;
RECT rect;
BOOL answer = GetWindowRect(hWnd, &rect); // Pass pointer to C structure

Using the CRect class, you can just pass the object, and the LPRECT operator will take care of the rest (but you can add the & if you really want to):使用CRect class,您可以只传递 object, LPRECT运算符将处理 rest(但如果您真的想要,可以添加& ):

HWND hWnd;
CRect rc;
BOOL answer = GetWindowRect(hWnd, rc);

There are limitations and caveats involved in this approach (eg horrid things may happen if the C library expects a RECT to be passed by value ), but it may be an approach you find helpful.这种方法存在一些限制和注意事项(例如,如果 C 库希望RECT按值传递,则可能会发生可怕的事情),但它可能是一种您认为有用的方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM