MST
星途 面试题库

面试题:Objective-C可变参数宏与泛型编程的结合及优化

在Objective-C中,尝试结合可变参数宏和泛型编程(如果可能的话),实现一个通用的函数调用器宏 `CALL_FUNCTION`。这个宏接收一个函数指针和可变数量的参数,它能够根据传递的函数指针和参数类型,正确调用对应的函数,并处理不同函数的返回值。要求代码具有高度的通用性和可扩展性,尽可能考虑到不同类型函数和参数的各种情况。请详细说明设计思路,并给出完整的代码实现。
49.9万 热度难度
编程语言Objective-C

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 可变参数宏:使用 ... 来表示可变数量的参数,并通过 __VA_ARGS__ 来引用这些参数。
  2. 泛型编程:Objective-C 没有像 C++ 那样原生的泛型支持,但我们可以利用 id 类型来实现一定程度的通用性。id 类型可以指向任何 Objective-C 对象,对于基本数据类型,我们可以使用 NSNumber 等类进行包装。
  3. 函数指针:接收函数指针作为参数,这样可以灵活地指定要调用的函数。
  4. 返回值处理:对于不同类型的返回值,我们可以使用 id 来统一接收,对于非对象类型的返回值,进行适当的转换或包装。

代码实现

#import <Foundation/Foundation.h>

// 定义一个宏来调用函数
#define CALL_FUNCTION(func, ...) \
({ \
    id result = nil; \
    if (func) { \
        va_list args; \
        va_start(args, __VA_ARGS__); \
        // 这里假设函数返回值为id类型,如果不是,需要特殊处理
        result = func(__VA_ARGS__); \
        va_end(args); \
    } \
    result; \
})

// 示例函数1:返回NSString对象
NSString *exampleFunction1(NSString *str) {
    return [NSString stringWithFormat:@"Processed: %@", str];
}

// 示例函数2:返回NSNumber对象
NSNumber *exampleFunction2(int num) {
    return @(num * 2);
}

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // 调用示例函数1
        id result1 = CALL_FUNCTION(exampleFunction1, @"Hello");
        NSLog(@"%@", result1);
        
        // 调用示例函数2
        id result2 = CALL_FUNCTION(exampleFunction2, 5);
        NSLog(@"%@", result2);
    }
    return 0;
}

在上述代码中:

  1. CALL_FUNCTION 宏接收一个函数指针 func 和可变参数 __VA_ARGS__
  2. 使用 va_list 来处理可变参数,在实际调用函数时传递这些参数。
  3. 假设函数返回值为 id 类型,如果函数返回的是非对象类型,例如 intfloat 等,需要进行特殊处理,这里示例中使用 NSNumber 来包装基本数据类型返回值。
  4. 定义了两个示例函数 exampleFunction1exampleFunction2,分别返回 NSStringNSNumber 对象,并通过 CALL_FUNCTION 宏进行调用,展示了宏的使用方式。