我读了很多关于
的问题
declaration of functions inside structure?
但我没有得到满意的答案。
我的问题不在于whether functions can be declared inside a structure or not?
相反,我的问题是
WHY function can not be declared inside structure?
答案 0 :(得分:9)
这就是C和C ++之间的根本区别(在C ++中有效)。 C ++支持类(在C ++中,struct
是类的特例),C不支持。
在C中,您将实现该类作为一个结构,其中的函数显式地采用this
指针,这实际上是C ++在幕后所做的事情。结合一个合理的命名约定,让你知道哪些函数属于哪些类(再次是C ++在名称修改过程中所做的事情),如果不是面向对象的编程,你就会接近基于对象的。例如:
typedef struct temp
{
int a;
} classTemp ;
void classTemp_GetData( classTemp* pThis )
{
printf( "Enter value of a : " );
scanf( "%d", &(pThis->a) );
}
classTemp T ;
int main()
{
classTemp_GetData( &T );
}
但是,正如你所看到的那样,如果没有语言支持,那么实现就会变得很烦人。
在C中,函数和数据结构或多或少是裸露的;该语言为将数据结构组合在一起提供了最少的支持,并且根本没有(直接)用于包含具有这些数据结构的函数。
C的目的是让一种语言尽可能直接地转换为机器代码,更像是一种可移植的汇编语言,而不是像C ++这样的高级语言(而不是C ++就是高级语言)。 C让你非常接近机器,深入了解大多数语言摘录的细节;这方面的缺点是你必须接近C中的机器才能最大限度地使用这种语言。它采用完全不同的方法从C ++进行编程,它们之间的表面相似性隐藏起来。
查看here了解更多信息(精彩的讨论)。
P.S。:您还可以使用函数指针来完成功能,即
在struct
内有一个指向函数(作为变量)的指针。
例如:
#include <stdio.h>
struct t {
int a;
void (*fun) (int * a); // <-- function pointers
} ;
void get_a (int * a) {
printf (" input : ");
scanf ("%d", a);
}
int main () {
struct t test;
test.a = 0;
printf ("a (before): %d\n", test.a);
test.fun = get_a;
test.fun(&test.a);
printf ("a (after ): %d\n", test.a);
return 0;
}
答案 1 :(得分:4)
为什么函数不能在结构内声明?
因为C标准不允许在结构中声明函数/方法。 C不是面向对象的语言。
结构或联合不得包含不完整或功能类型的成员(因此, 结构不应包含自身的实例,但可以包含指向实例的指针 它本身),除了具有多个命名成员的结构的最后一个成员 可能有不完整的数组类型;这样的结构(和任何包含的结合,可能 递归地,这种结构的成员不应该是结构的成员或者 数组的元素。
答案 2 :(得分:0)
我想有很多原因,其中有几个:
C编程语言创建于1972年,受纯汇编语言的影响,因此struct被认为是“仅数据”元素
一旦C不是面向对象的语言 - 实际上没有意义在“数据结构”中定义函数,没有构造函数/方法等实体
函数直接转换为纯汇编push
和call
指令,并且没有隐藏的参数,例如this
答案 3 :(得分:0)
我想,因为它在C语言中没有多大意义。如果你在结构中声明一个函数,你会期望它与某个结构有某种关系,对吧?说,
struct A {
int foo;
void hello() {
// smth
}
}
您希望hello()
至少可以访问foo
吗?因为否则hello()
只得到类似命名空间的东西,所以为了调用它我们会写A.hello()
- 就C ++来说它将是一个静态函数 - 与普通的C函数差别不大。
如果hello()
有权访问foo
,则必须有this
指针来实现此类访问,这在C ++中始终隐式地作为第一个参数传递给函数。
如果结构函数可以访问结构变量,那么它必须与具有其他函数的访问在某种程度上不同,同样,在结构中添加一些功能。我们有public
,private
修饰符。
下一步。你没有在C中继承(但你可以模拟它),这是在结构化中声明函数增加很多东西的东西。所以我们在此处添加virtual
和protected
。
现在你可以添加名称空间和类,在这里你发明了C ++(好吧,没有模板)。
但是C ++是面向对象的,而C则不是。首先,人们创建了C,然后他们编写了大量的程序,理解了可以做出的一些改进,然后,按照我之前提到的推理,他们想出了C ++。他们并没有改变C而是分离概念--C是面向过程的,而C ++是面向对象的。
答案 4 :(得分:0)
C的设计使其可以使用相对简单的编译系统进行处理。要允许函数定义出现在任何其他内容中,需要编译器跟踪函数在处理时出现的上下文。鉴于结构,联合或枚举声明的成员在声明结束之前不会输入作用域,因此在结构中声明的函数可能无法执行其他地方声明的函数。
从概念上讲,允许在结构中进行常量声明可能会很好;一个指向文字函数的常量指针就是一个特例(即使函数本身必须在其他地方声明),但这需要C编译器跟踪每个结构成员的更多信息 - 而不仅仅是它的类型和偏移量,但它是否是一个常数,如果是,它的价值应该是什么。在今天的编译环境中,这样的事情并不困难,但是早期的C编译器预计运行的内存比目前的数量少。
鉴于C已被扩展为提供许多功能,这些功能无法由运行在64K(或更小)系统上的编译器处理,因此可以合理地认为它不再受这些约束的约束。实际上,我希望丢失C的遗产的某些方面,例如整数提升规则,它们甚至要求新的整数类型遵循旧类型的不一致规则,而不是允许新类型具有明确指定的行为[例如有一个wrap32_t
可以转换为任何其他整数类型而没有类型转换,但当添加到任何“非包装”整数类型任何大小将产生wrap32_t
]。能够在结构中定义函数可能会很好,但是在我的改进列表中它将会非常接近。