现代C和C :可以将一个定义的结构用于其他声明的结构
Modern C and C++: it is possible to use one defined structure for other declared structure?
假设我想制作某种引擎,以支持加载图形Image
s,所以我有
struct Image;
Image* load_image_from_file(...);
我不希望外部世界知道Image
的确是什么,他们只会处理指针。
但是,在engine
内,我想使用特定类型,例如SDL_Surface
在SDL中完全定义。
我可以以某种方式重新重新用于此文件的图像,因此编译器每次看到Image*
(除宏除外)时都假定SDL_Surface*
?
即。我想要typedef struct SDL_Surface Image;
所有尝试都像
using Image = SDL_Surface;
typedef SDL_Surface Image;
typedef struct SDL_Surface Image;
产生编译时间错误(http://codepad.org/1cfn18oh)。
我知道我可以在engine.c
/engine.cpp
中使用struct Image{SDL_Surface* surface};
,但它会创建不必要的间接方式,我必须键入->surface
。另一个肮脏的解决方案是使用明确的铸件,例如((SDL_Surface*)image)
,但我在重命名的清洁剂中很有趣。
ps。我对C和C 的答案感兴趣。
简单地定义一个别名:
using Image = SDL_Surface;
typedef SDL_Surface Image;
汇编正好。
如果您需要隐藏SDL_Surface
,只需将其导入某些匿名或detail
名称命名空间并将其类似地导入。
如果出于某些原因,您要定义自己的Image
类型,则可以随时声明A(n)(隐式)转换功能/操作员,例如:
struct Image {
/* explicit */ operator SDL_Surface() const;
// ...
};
,也可以返回Image
,如果您需要:
struct Image {
/* explicit */ Image(SDL_Surface&&);
/* explicit */ Image(SDL_Surface const&);
// ...
};
在C 中您可以使用继承:
// User view
struct Image; // forward declaration (inclomplete type).
Image* LoadFromFile (...); // You can use pointer to incomplete type
// Implementation view
struct Image: SDL_Surface { }; // here you go !! :-)
备注:使用类和私人继承会更安全,因此只有图像知道它是一个sdl_surface。
在某些情况下,从现有的实现类中继承可能是不希望的(例如,如果您需要虚拟驱动器,而基类无需)。然后,pimpl习语可以是替代方案(以额外的间接为代价):
//User View unchanged
struct Image;
int TestImage(Image*z);
//implementation view
struct Image {
struct ImageImpl { int x; }; // nested definition or typedef or whatever
ImageImpl *p; // works in every case, at cost of an extra indirection instead of a pointer
};
int TestImage(Image* z)
{
return z->p->x;
}
PIMPL的主要优点是,您不仅可以公开不完整的类型,因此可以向客户提供一些有用的成员功能。但是,如果您不需要这个,并且由于您已经与POITNER一起使用了客户端的对象,那么您也可以直接转到组成并拥有ImageImpl
成员而不是PIMPL指针。
在C 中,您不能使用继承。但是构图肯定会解决问题:
struct Image {
SDL_Surface s;
};
通常使用PIMPL(指向实现)模式进行此类操作。但是,如果您想暂时避免间接,或者类型不完整(SDL_Surface
不是这种情况,但是与许多其他SDL类相关),则可以使用void
的指针,因为它可以指向任何数据,然后将其施放在实施方面。
在这里,我们使用std::unique_ptr
使用零规则。这种Image
现在是不可复制的,但可移动。如果您想能够复制它,请使用 value_ptr
-like指针(不在标准中,但可以轻松地写下这样的指针或使用第三方)
#include <memory>
struct ImageDeleter
{
void operator()(void* ptr) const;
};
class Image
{
public: // but don't touch it
std::unique_ptr<void, ImageDeleter> internal;
private:
/* private operations on surface */
public:
/* public operations */
void save(const std::string& path) const;
Image(int width, int height);
};
// EXAMPLE USAGE
// Image img(640, 480);
// img.save("aaa.bmp");
// IN THE DEFINITION FILE
#include <SDL2/SDL.h>
namespace detail
{
SDL_Surface* as_surface(const Image& img)
{
return static_cast<SDL_Surface*>(img.internal.get());
}
}
void ImageDeleter::operator()(void* ptr) const
{
SDL_FreeSurface(static_cast<SDL_Surface*>(ptr));
}
Image::Image(int width, int height) :
internal(SDL_CreateRGBSurface(0, width, height, 32, 0, 0, 0, 0))
{
}
void Image::save(const std::string& path) const
{
SDL_SaveBMP(detail::as_surface(*this), path.c_str());
}
如果您的客户端代码对图像没有任何作用,除了传递指针,您可以使用Windows API技巧:
typedef void *HIMAGE; // Image Handle
HIMAGE LoadImage(...);
在C 中您可以求助于不完整的类型。
因此,您在标题文件中定义API:
myapi.h
struct Image;
struct Image* load_image_from_file(...);
...
请注意,您的struct Image
类型虽然适用于您的客户,但已完全隐藏。
现在您的实施完成了您的结构的完整声明:
myapi.c:
struct Image {
/* whatever you want to put here */
/* even SDL_Surface */
/* or pointer to it */
};
/* function bodies */
您将编译的C代码(对象,静态或动态库)和客户的标题捆绑在一起。
在您导出的标题中,您可以转发SDL_Surface
然后将Image
声明为指针。喜欢:
struct SDL_Surface;
typedef SDL_Surface* Image;
extern Image load_image_from_file(char*);
这样,可以在没有SDL标题的情况下使用库。
但是,仍然需要sdl.dll。
- 预处理器:插入结构名称中的前一个行号
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 我不明白为什么我声明一个空的内部结构并将其传递给构造函数
- 静态结构和一个定义规则
- 为什么将一个结构的引用设置为等于另一个结构只会更改一个数据成员?
- C++ - 如何在结构向量中找到结构体一个成员的最大值?
- 如何在 C++11 中查找和更新向量中的一个嵌套结构
- 在学习数据结构之前对STL有一个了解是好的吗?
- 给定一个C++嵌套的私有结构类型,是否有从文件范围静态函数访问它的策略
- 从另一个 cpp 文件更改结构内、映射键内的变量
- 如何将一个结构的字符数组复制到结构的另一个字符数组中?
- 使用完数据结构后清空数据结构是一个好习惯吗?
- 如何制作一个地图,其中的值是C++中的结构数组
- 如何将数据从一个结构链接到另一个结构
- 是否可以使用智能指针成员设置具有另一个结构的结构?
- error dllimport 函数的定义不允许在一个特定的联合中,而其他类、结构和联合将按预期导出
- std::transform 将一个结构数组复制到另一个结构数组
- C++:如何做一个链表,结构作为参数传递?
- 输入 ctrl + x 后如何再次 cin (cin<<x) 循环(cin 一个结构)
- 两个附带的类层次结构-一个好的设计模式