关于结构体的一些细节问题

结构体中的易错点


作为一名蒟蒻,我常常在各种各样的编程问题上磕磕绊绊。今天又是这样。

问题 I

大致就是当我声明了一个结构体edge,然后又自定义了一个构造函数edge(int …)(带参的),然后。。。我想要声明一个edge的数组,编译器却一直在报错:
(部分代码如下)

typedef struct edge{
    int n,u,v,l;
    edge(int n,int u,int v,int l){
        this->n=n;
        this->u=u;
        this->v=v;
        this->l=l;
    }
}edge;
edge e[maxn];

(编译器报错如下)

[Error] no matching function for call to ‘edge::edge()’

然后我就调啊调,最后在网上找到了一篇文章,终于解决了我的问题,下面我就来分享一下

解决方案

定义结构体数组要有默认构造函数才行,如果你没有定义构造函数,那编译器就会自动给你生成一个,但只要你定义了构造函数,编译器就不再帮你生成了,所以你的错误是没有默认构造函数,要改的话,给你上面那个构造函数的参数全部加上缺省值就可以了————来自某好心人

这个的意思是我还应该再编写一个无参构造函数,因为原来的那个被我重载掉了。。。
加上下面这一段代码就好了(在结构体内部加入):

edge():n(0),u(0),v(0),l(0){}

于是这个问题就这样过去了

问题 II

后来在给结构体数组赋值时,我是这样写的:

e[i]=new edge(i,x,y,l);

然后就又错了

然而我改成这样就正确了:

e[i]=edge(i,x,y,l);

应该是new只能给指针类型的初始化吧,我这个已经有了构造函数直接赋值就好,总之C++真是博大精深

╮(╯▽╰)╭。。。我真是太弱了

<think>嗯,用户问为什么在.h文件中不隐藏shiw结构体细节。我需要先理解他们的背景和需求。用户之前询问了如何让函数返回shiw类型,现在他们可能在考虑封装和信息隐藏的问题,这在C语言中确实是个重要的话题。 首先,回顾之前的回答,示例代码在.h文件中定义了shiw结构体,这意味着所有包含该头文件的代码都能看到结构体的内部细节。用户可能已经了解到,暴露结构体细节会破坏封装性,导致其他代码直接依赖其内部结构,增加耦合度,不利于维护。所以,用户可能想了解如何隐藏结构体细节,或者为什么之前的例子没有这样做。 接下来,我需要解释为什么有时候在头文件中暴露结构体细节是必要的。在C语言中,如果结构体被用作值传递(比如函数返回结构体实例),编译器需要知道结构体的大小和布局来正确管理栈空间和进行拷贝操作。如果结构体细节被隐藏(即使用不透明指针),那么只能通过指针来操作结构体,此时结构体的定义在实现文件中,头文件只有声明,但用户无法直接创建实例或访问成员,必须通过函数来操作。 然后,用户可能想知道如何选择这两种方式。如果结构体需要按值传递,必须在头文件中公开细节;如果希望隐藏实现,可以使用不透明指针,但这样就不能按值传递,只能通过函数返回指针,并且需要提供创建和销毁的函数。这种情况下,用户可能需要权衡封装性和性能。 用户可能还有更深层的需求,比如如何设计更安全的API,或者如何优化性能。他们可能是在开发一个库,希望隐藏实现细节,但之前的示例没有这样做,所以需要解释不同方法的适用场景。 需要指出在之前的示例中,结构体被按值返回,因此必须公开细节。如果用户希望隐藏,可以改用不透明指针,并提供相应的接口函数。同时,要说明两种方法的优缺点,比如按值传递的简单性但潜在的性能问题,以及指针方式的信息隐藏但需要动态内存管理。 还要注意用户可能的后续问题,比如如何实现不透明指针,或者如何处理结构体较大的情况下的性能优化。这些可能需要进一步解释,但当前问题主要集中在为什么.h文件不隐藏结构体,所以需要紧扣这一点,给出清晰的对比和理由。 总结回答的结构:首先解释为什么示例中没有隐藏结构体细节(因为按值传递需要编译器知道结构体大小),然后说明隐藏结构体的方法(不透明指针),并对比两者的使用场景和优缺点,最后给出建议的选择依据。</think>--- 在C语言中,`.h` 文件(头文件)是否隐藏结构体细节取决于设计需求。**如果未隐藏 `shiw` 结构体细节,通常是为了允许外部代码直接访问其成员**。以下是详细解释和两种设计模式的对比: --- ### 为什么不隐藏结构体细节? 1. **按值操作的需求** - 如果函数需要**按值返回结构体**(如 `shiw func(...)`)或**按值传递参数**,编译器必须知道结构体的完整定义(成员类型和内存布局),才能正确分配栈空间并执行拷贝操作。 - 示例中 `create_shiw` 函数返回的是 `shiw` 类型的值,因此必须在头文件中公开结构体定义。 2. **简化访问逻辑** - 允许外部代码直接读写结构体的成员(如 `obj.data = 10`),无需通过函数接口(如 `set_data(&obj, 10)`),适合简单场景。 --- ### 如何隐藏结构体细节? 如果希望隐藏实现细节(封装性),需改用**不透明指针(Opaque Pointer)**模式: 1. **在 `.h` 文件中仅声明结构体类型**,不公开成员: ```c // .h 文件 typedef struct shiw shiw; // 不完整类型声明 shiw* create_shiw(int data, const char *name); // 返回指针 void destroy_shiw(shiw *obj); // 释放内存 int get_data(const shiw *obj); // 通过接口访问成员 ``` 2. **在 `.c` 文件中定义结构体细节**: ```c // .c 文件 struct shiw { // 完整定义(仅在此处可见) int data; char name[50]; }; shiw* create_shiw(...) { shiw *obj = malloc(sizeof(shiw)); // 动态分配内存 // 初始化成员 return obj; } ``` --- ### 两种模式的对比 | **特性** | **公开结构体细节** | **隐藏结构体细节(不透明指针)** | |-----------------------|------------------------------------|---------------------------------------| | **成员访问** | 直接访问(如 `obj.data`) | 必须通过接口函数(如 `get_data(obj)`)| | **内存管理** | 栈或静态分配(按值传递) | 需动态分配(`malloc`/`free`) | | **封装性** | 低(外部依赖内部实现) | 高(实现可随意修改,不影响用户代码) | | **性能** | 高(无指针间接访问开销) | 较低(指针解引用、函数调用开销) | | **适用场景** | 小型结构体、高频操作 | 大型结构体、需严格封装的库设计 | --- ### 选择依据 - **需要按值传递结构体** ➔ 必须公开细节(如示例代码)。 - **需要封装性/灵活性** ➔ 使用不透明指针,但需改用指针传递。 - **性能敏感场景** ➔ 优先公开细节,避免动态内存分配和函数调用开销。 --- ### 总结 示例代码未隐藏 `shiw` 的细节,是因为它**直接操作结构体值**。若需隐藏实现,需改用指针传递并配套接口函数,但会牺牲部分性能和简洁性。两种方案各有优劣,需根据具体需求权衡。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值