为什么我们不能在结构中声明函数?

时间:2014-02-22 06:22:21

标签: c function struct declaration

我读了很多关于

的问题
  

declaration of functions inside structure?

但我没有得到满意的答案。

我的问题不在于whether functions can be declared inside a structure or not?

相反,我的问题是

  

WHY function can not be declared inside structure?

5 个答案:

答案 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不是面向对象的语言。

6.7.2.1结构和联合说明符:

  

结构或联合不得包含不完整或功能类型的成员(因此,   结构不应包含自身的实例,但可以包含指向实例的指针   它本身),除了具有多个命名成员的结构的最后一个成员   可能有不完整的数组类型;这样的结构(和任何包含的结合,可能   递归地,这种结构的成员不应该是结构的成员或者   数组的元素。

答案 2 :(得分:0)

我想有很多原因,其中有几个:

  1. C编程语言创建于1972年,受纯汇编语言的影响,因此struct被认为是“仅数据”元素

  2. 一旦C不是面向对象的语言 - 实际上没有意义在“数据结构”中定义函数,没有构造函数/方法等实体

  3. 函数直接转换为纯汇编pushcall指令,并且没有隐藏的参数,例如this

答案 3 :(得分:0)

我想,因为它在C语言中没有多大意义。如果你在结构中声明一个函数,你会期望它与某个结构有某种关系,对吧?说,

struct A {
  int foo;
  void hello() {
    // smth
  }
}

您希望hello()至少可以访问foo吗?因为否则hello()只得到类似命名空间的东西,所以为了调用它我们会写A.hello() - 就C ++来说它将是一个静态函数 - 与普通的C函数差别不大。

如果hello()有权访问foo,则必须有this指针来实现此类访问,这在C ++中始终隐式地作为第一个参数传递给函数。 如果结构函数可以访问结构变量,那么它必须与具有其他函数的访问在某种程度上不同,同样,在结构中添加一些功能。我们有publicprivate修饰符。

下一步。你没有在C中继承(但你可以模拟它),这是在结构化中声明函数增加很多东西的东西。所以我们在此处添加virtualprotected

现在你可以添加名称空间和类,在这里你发明了C ++(好吧,没有模板)。

但是C ++是面向对象的,而C则不是。首先,人们创建了C,然后他们编写了大量的程序,理解了可以做出的一些改进,然后,按照我之前提到的推理,他们想出了C ++。他们并没有改变C而是分离概念--C是面向过程的,而C ++是面向对象的。

答案 4 :(得分:0)

C的设计使其可以使用相对简单的编译系统进行处理。要允许函数定义出现在任何其他内容中,需要编译器跟踪函数在处理时出现的上下文。鉴于结构,联合或枚举声明的成员在声明结束之前不会输入作用域,因此在结构中声明的函数可能无法执行其他地方声明的函数。

从概念上讲,允许在结构中进行常量声明可能会很好;一个指向文字函数的常量指针就是一个特例(即使函数本身必须在其他地方声明),但这需要C编译器跟踪每个结构成员的更多信息 - 而不仅仅是它的类型和偏移量,但它是否是一个常数,如果是,它的价值应该是什么。在今天的编译环境中,这样的事情并不困难,但是早期的C编译器预计运行的内存比目前的数量少。

鉴于C已被扩展为提供许多功能,这些功能无法由运行在64K(或更小)系统上的编译器处理,因此可以合理地认为它不再受这些约束的约束。实际上,我希望丢失C的遗产的某些方面,例如整数提升规则,它们甚至要求新的整数类型遵循旧类型的不一致规则,而不是允许新类型具有明确指定的行为[例如有一个wrap32_t可以转换为任何其他整数类型而没有类型转换,但当添加到任何“非包装”整数类型任何大小将产生wrap32_t ]。能够在结构中定义函数可能会很好,但是在我的改进列表中它将会非常接近。