简体   繁体   English

就像在C#类构造函数中一样,在C结构中设置变量

[英]Setting Variables in a C struct just like in a C# class constructor

In C#, inside a class, we can have variables that are set during the constructor of the type, like such: 在C#的类内部,我们可以在类型的构造函数中设置变量,例如:

class ComplexNumber
{
 public double real {get; set;}
 public double imag {get; set;}
 public double abs {get;}
 public Complex Number(double real, double imag)
 {
  this.real = real;
  this.imag = imag;
  this.abs = Math.Pow(real*real + imag*imag , 0.5f);
 }
}

(I apologize if the C# code is wrong, I haven't written C# in a while and I'm using it purely for an analogy ) During the constructer, the value of 'abs' is set, so I wanted to know if in a C struct, it'd be possible to do the same, even though there is no constructor (如果C#代码错误,我很抱歉,我有一段时间没有写C#了,我只是出于类推的目的而使用它。)在构造函数期间,设置了'abs'的值,所以我想知道是否在C结构,即使没有构造函数,也可以做同样的事情

typedef struct Comp
{
 double real;
 double imag;
 double abs;
} Comp;

int main(void)
{
 Comp z;
 z.real = 2.0f;
 z.imag = 5.3f;
 printf("%f\n" , z.abs);
}

So I'd like to be able to run the code up there and have it return a value for z.abs without ever actually setting it to anything (although it being set to something after both z.real and z.imag are set). 因此,我希望能够在那里运行代码,并使其返回z.abs的值,而无需实际将其设置为任何值(尽管在同时设置z.real和z.imag之后将其设置为某些值) 。 Would this be feasible somehow in C? 在C中以某种方式可行吗?

edit: I have looked as Default values in a C Struct as suggested and in that question, they seem to want a default value for their own type, so a type that is preset, but on my case, what I would like to be able to do is, instead of setting the custom type to a default, every time I set a custom type, one of the attributes inside of it, 'z.abs' would be set using 'z.real' and 'z.imag' instead of having a default value, for examples: 编辑:我已经按照建议将其作为C结构中的默认值,在这个问题中,他们似乎想要自己的类型为默认值,所以该类型是预设的,但就我而言,我希望能够要做的是,不是将自定义类型设置为默认值,而是每次设置自定义类型时,将使用其中的一个属性“ z.abs”使用“ z.real”和“ z.imag”进行设置而不是使用默认值,例如:

Comp z;
z.real = 4.0f;
z.imag = 3.0f;

After writting this code, z is defined as { 4.0f, 3.0f, null/undefined}, but the last part of it, 'abs' can be calculated using the first two as sqrt(z.real^2 + z.imag^2) and so it's value is 5.0f. 编写此代码后,将z定义为{4.0f,3.0f,null / undefined},但可以使用前两个作为sqrt(z.real ^ 2 + z.imag)来计算其最后一部分“ abs” ^ 2),因此它的值为5.0f。 So I would want to, after setting the first two numbers, for the third one to be calculated automatically like a constructor in C#, the first example. 因此,我希望在设置前两个数字之后,像第一个示例中的C#中的构造函数那样自动计算第三个数字。

Given your C# code, what you have is a readonly automatic property. 给定您的C#代码,您拥有的是一个readonly自动属性。 You could write your C# code instead like this: 您可以这样编写C#代码:

class ComplexNumber
{
 public double real;
 public double imag;
 public readonly double abs;
 public ComplexNumber(double real, double imag)
 {
  this.real = real;
  this.imag = imag;
  this.abs = Math.Pow(real*real + imag*imag , 0.5f);
 }
}

For a moment, forget that this isn't the best style in C#. 暂时,请记住这不是C#中最好的样式。 The relevant change is, your class now has just fields instead of properties and you can do something quite similar in C: 相关的变化是,您的类现在仅具有字段而不是属性,并且您可以在C中执行类似的操作:

#include <stdio.h>
#include <math.h>

struct ComplexNumber
{
    double real;
    double imag;
    const double abs;
};

#define ComplexNumber_init(r,i) { \
    .real=(r), .imag=(i), .abs=pow((r)*(r)+(i)*(i), .5) }

int main(void)
{
    struct ComplexNumber cnum = ComplexNumber_init(4.0, 2.0);
    printf("%f\n", cnum.abs);
}

The key component here is the const qualifier on one struct member. 这里的关键组件是一个struct成员上的const限定符。 With this, you can only set the value at initialization time, never later. 这样,您只能在初始化时设置该值,以后再也不能设置。 The effect is quite comparable to C#'s readonly . 其效果与C#的readonly相当。 C# has const , too, but with readonly , you can additinally set the value in the constructor. C#也具有const ,但是使用readonly ,您可以在构造函数中另外设置值。


If you want an equivalent to your original C# code, you must be aware that properties in C# always translate to methods -- getters and setters. 如果要与原始C#代码等效,则必须知道C#中的属性总是转换为方法-getter和setter。 In your example, you're using automatic properties , that means, as you don't specify a function body for your getters and setters, a default body is automatically created for you, simply accessing a private field. 在您的示例中,您使用的是自动属性 ,这意味着,由于您没有为getter和setter指定函数主体,因此会为您自动创建一个默认主体,只需访问一个私有字段即可。

There's no such thing in C, but you can create the same thing manually, an example follows. C语言中没有这样的东西,但是您可以手动创建相同的东西,下面是一个示例。

Note I changed the semantics a bit, because having real and imag changeable without ever updating abs , as this is the case in your C# code, probably isn't the most sensible thing to do. 注意,我对语义进行了一些更改,因为在不更新abs的情况下就可以更改realimag ,因为这在您的C#代码中就是这种情况,这可能不是最明智的选择。

Also note this is complete overkill for this little example case, I'm just adding it to show a possibility how to write a "class" in C. 还要注意,对于这个小例子来说,这是完全矫kill过正的,我只是添加它来说明如何用C编写“类”。

compnum.h: compnum.h:

#ifndef COMPNUM_H
#define COMPNUM_H

typedef struct ComplexNumber ComplexNumber;

// "constructor":

ComplexNumber *ComplexNumber_create(double real, double imag);

// getters and setters:

double ComplexNumber_real(const ComplexNumber *self);
void ComplexNumber_setReal(ComplexNumber *self, double real);

double ComplexNumber_imag(const ComplexNumber *self);
void ComplexNumber_setImag(ComplexNumber *self, double imag);

double ComplexNumber_abs(const ComplexNumber *self);

// "destructor":

void ComplexNumber_destroy(ComplexNumber *self);

#endif

compnum.c: compnum.c:

#include <math.h>
#include <stdlib.h>

#include "compnum.h"

// the struct itself is completed here and not in compnum.h -- this way, its
// members are *really* "private". They can't be seen by other translation
// units just including compnum.h.
struct ComplexNumber
{
    double real;
    double imag;
    // don't need abs here, it's calculated
};

ComplexNumber *ComplexNumber_create(double real, double imag)
{
    ComplexNumber *self = malloc(sizeof(*self));
    if (!self) return 0;
    self->real = real;
    self->imag = imag;
    return self;
}

double ComplexNumber_real(const ComplexNumber *self)
{
    return self->real;
}

void CompexNumber_setReal(ComplexNumber *self, double real)
{
    self->real = real;
}

double ComplexNumber_imag(const ComplexNumber *self)
{
    return self->imag;
}

void ComplexNumber_setImag(ComplexNumber *self, double imag)
{
    self->imag = imag;
}

double ComplexNumber_abs(const ComplexNumber *self)
{
    return pow(self->real*self->real + self->imag*self->imag, .5);
}

void ComplexNumber_destroy(ComplexNumber *self)
{
    free(self);
}

main.c: main.c:

#include <stdio.h>

#include "compnum.h"

int main(void)
{
    ComplexNumber *cnum = ComplexNumber_create(4.0, 2.0);
    printf("%f\n", ComplexNumber_abs(cnum));
    ComplexNumber_destroy(cnum);
}

If you don't explicitly set a field in a struct, it's contents are unspecified. 如果未在结构中显式设置字段,则其内容未指定。

You can initialize the values of the struct as follows: 您可以按以下方式初始化该结构的值:

Comp z = { 0.0, 0.0, 0.0 };

If you want to "initialize" a new struct to some predetermined values, some of which must be calculated from the values of other members, you can use a function that returns a struct : 如果要将新struct “初始化”为一些预定值,其中某些必须从其他成员的值计算而来,则可以使用返回struct

#include <stdio.h>
#include <math.h>

typedef struct Comp
{
 double real;
 double imag;
 double abs;
} Comp;

Comp new_Comp(double re, double im);

int main(void)
{
    Comp my_comp = new_Comp(3.0, 4.0);

    printf("my_comp.real = %f, my_comp.imag = %f, my_comp.abs = %f\n",
           my_comp.real, my_comp.imag, my_comp.abs);

    return 0;
}

Comp new_Comp(double re, double im)
{
    Comp new = { .real = re, .imag = im };
    new.abs = hypot(re, im);

    return new;
}

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

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