'类' C中的行为

时间:2014-12-26 18:38:12

标签: c oop struct

说我有这个:

struct Person {
    char *name;
    char *occupation;
    int years_of_service;
    float salary;
};

和此:

float calculate_salary(struct Person *who){
    float basesalary;

    char *doctor = "Doctor";
    char *janitor = "Janitor";

    int job1 = strcmp(who->occupation, doctor);
    int job2 = strcmp(who->occupation, janitor);

    if(job1 == 0){
        basesalary = 10000.0;
    }
    else if(job2 == 0){
        basesalary = 800.0;
    }

    return basesalary + basesalary*(who->years_of_service*0.1);
}

计算人的工资的正确方法是什么?

在Python中

我会在init中执行它:

self.salary = self.calculate_salary()

但由于C不是OO,我假设我必须首先创建一个没有薪水的人,然后设置薪水。像这样:

struct Person *joe = Person_create("Joe Alex", "Doctor",1);
joe->salary = calculate_salary(joe);

但我希望有更好理解C的人告诉我这是否正确。

作为旁注,字符串同情是正确的吗?我发现这很奇怪,我应该使用开关吗?

2 个答案:

答案 0 :(得分:9)

  

计算人的工资的正确方法是什么?

您正在做的是使用普通struct作为对象并通过指针将其传递给函数。您已经在C中使用面向对象的方法。

如果您对实现python中显示的效果感兴趣,请在结构calculate_salary中添加指向函数Person的指针。

struct Person {
    char *name;
    char *occupation;
    int years_of_service;
    float salary;
    float (*fptr)(struct Person *); // fptr is a function pointer
};    

这是一个驱动程序:

int main(void)
{
    struct Person *joe = malloc(sizeof(struct Person));
    joe->name = "Joe Alex";
    joe->occupation = "Doctor";
    joe->years_of_service = 1;

    joe->fptr = calculate_salary; //Function pointer Assignment
    (*joe).salary = (*joe).fptr(joe);
    printf("%f", joe->salary);
}  

你应该注意的一点是,上面结构中使用的函数指针主要用于写callback methods

答案 1 :(得分:6)

在C

中编写一个简单的getter

面向对象语言中的基本目的是为相同类型的对象提供一组操作。大多数情况下,操作采用方法的形式。如果我们忽略了示例中显然不需要的高级概念,则方法只是对特定类型的对象进行操作的函数子例程

这些方法可以在C中实现,就像任何其他函数一样,这正是您calculate_salary()的实现。您可能希望将其重命名为遵循以下惯例:C中的此类函数以类型名称为前缀,例如, person_get_salary()

实施班级

您根本不需要结构中的salary字段,因为您将使用person_get_salary()函数(或方法)访问它。

struct person {
    char *name;
    char *occupation;
    int years_of_service;
};

float person_get_salary(struct person *person)
{
    ...
}

然后简单地使用它。

float salary = person_get_salary(person);

以上是方法调用的以下伪代码的C语法。

float salary = person.get_salary();

或者基于以下属性的伪代码。属性看起来像语法中的字段,但是在后台使用 getter setter 方法实现。

float salary = person.salary;

使用这些结构仍有两种主要方法,因为C 非常灵活,可以实现各种OOP位。

在堆栈上分配的对象

来电者可以为此人提供存储空间。优点是存储可以很好地存储在堆栈中。

struct person person;

person_init(&person, ...);

float salary = person_get_salary(&person);

...

person_cleanup(&person);

在堆上分配的对象

实现提供存储并在堆上分配对象。

struct person *person = person_new();

float salary = person_get_salary(person);

...

person_free(person);

实施说明

您需要相应地实施person_init()person_new()以及person_cleanup()person_free()。请注意,主要区别在于实现是否为对象分配和释放内存。在这两种情况下,nameoccupation的字符串通常都会被实现分配和释放。

关于函数指针的注释

另一个答案是关于解决问题不同方面的函数指针。

this 回答所示,简单方法可以实现为C函数,它接受指向对象的指针作为其第一个参数。函数指针对于高级功能(如通过虚方法的多态)非常有用。但即使这样,函数指针也存储在一个单独的结构中(通常称为虚方法表),该结构在相应类型的所有对象之间共享。

有些情况下,您可能希望直接在对象中存储函数指针,但这些指针通常用于回调而不是简单的getter。

替代方法

另一种方法是实际使用 salary 字段并在对象创建和/​​或修改时预先计算它。这样调用者只会从结构中读取 salary 字段,并且访问者函数(或方法)也不是必需的。