2

我有一个 C++ 类“ Expression”,其中包含我想在我的 Objective-C 类“ GraphVC”中使用的方法。

class Expression {
    double evaluate(double);
}

还有我的 Objective-C 类:

@implementation GraphVC : UIViewController {
- (void)plot:(double(*)(double))f;
@end

我认为与 C++ 对象相反,传递接受 double 并返回 double 的函数指针是最简单的,但我在使用functional.h. 从 Objective-C 使用我的 C++ 方法的最佳方式是什么?

编辑:感谢您的快速回复。请允许我详细说明一下...我有一个用 C++ 编写的后端,我在其中操作表达式类型的对象。有理数、多项式、单项式等的子类。我最初的想法是使用mem_fun from ,但我无法以这种方式编译代码。我在使用 bind1st 绑定this指针时也遇到了麻烦。

  • 编写一个 Objective-C 包装器是可能的,但我宁愿使用已经存在的evaluate()函数,而且我不想破坏后端和 iPhone GUI 类之间的清晰分离。
  • 我不能有全局表达式或使用静态方法(我需要绘制任意Expression实例。

我应该更明确地说明我需要将 C++ 成员函数(不是静态函数或现有 C 函数)传递给 Objective-C 对象。有没有人幸运地使用 C++<functional>将成员函数转换为可以在 Objective-C 对象中使用的指针,或者我应该使用 Objective-C 包装器?

4

5 回答 5

2

如果要在 C++ 中创建指向方法的指针,则需要包含类名,如下所示:

class Foo
{
  public:
    double bar(double d)
    {
      return d;
    }
};

void call_using_obj_and_method(Foo *f, double (Foo::*m)(double d))
{
  (f->*m)(3.0);
}

int main()
{
  Foo f;
  call_using_obj_and_method(&f, &Foo::bar);
  return 0;
}

请注意,您还需要该类的实例。在我的示例中,这是另一个参数,尽管您可以将其设为全局变量,或 Foo 类的单例实例。

不过,就像 jkp 所说,您也可以通过将方法设为静态或将其转换为常规函数来解决问题。

编辑:我不确定我是否正确理解了你的问题。我认为您不需要使用功能。这是我的示例在 Objective-C++ 中的外观:

#include <Cocoa/Cocoa.h>

class Foo
{
  public:
    double bar(double d)
    {
      return d;
    }
};

typedef double (Foo::*fooMethodPtr)(double d);

@interface Baz : NSObject
{
}
- (void)callFooObj:(Foo *)f method:(fooMethodPtr)m;
@end

@implementation Baz
- (void)callFooObj:(Foo *)f method:(fooMethodPtr)m
{
  (f->*m)(3.0);
}
@end

int main()
{
  Foo f;
  Baz *b = [[Baz alloc] init];
  [b callFooObj:&f method:&Foo::bar];
  return 0;
}
于 2009-07-27T13:33:57.907 回答
2

我建议将 C++ 类包装在一个 Objective-C 类中,然后还提供一个

- (void) plotWithObject:(id)obj
{
   double result = [obj evaluate: 1.5];
   // ... etc ...
}

除了情节:方法。

于 2009-07-27T13:39:20.987 回答
1

我认为这里的问题是你试图将你的Expression类的成员函数传递给 Objective-C 类。这将不起作用,因为它期望this指针作为该函数的第一个参数(因此签名与plot:方法所期望的不同。

如果您将 C++ 方法设为静态,则可以这样做,但是您不会因为使用标准 C 函数而为自己买太多东西。

IE,如果Expression类看起来像这样:

class Expression {
    static double evaluate(double);
}

你应该可以这样称呼它:

[self plot:myExpression.evaluate(&Express::evalulate)];

不过,正如我所说,这并没有很大的价值,因为您还不如使用标准的 C 函数(除非您可以在 C++ 类中做一些对您更有用的事情)。

我曾经看过尝试用 Objective-C 方法连接 boost::bind() 结果,但并没有走得太远。我敢肯定,如果您在 C++ 运行时中深入挖掘,您可以做到这一点。

于 2009-07-27T13:22:45.500 回答
0

如果你的 C++ 成员函数返回一个双精度,你的代码就不能看起来像这样吗?

- (void)plot:(double)f;

...

[self plot:myExpression.evaluate(aDouble)];

或类似的东西。我没有过多地混合使用 Obj-C 和 C++,但这就是我的处理方式。如果你像这样混合它们,你可能还必须在你的 Objective-C++ 文件上有一个 .mm 扩展名。

于 2009-07-27T12:26:35.983 回答
0

为什么不在 NSValue 中传递实例化的 c++ 类,然后直接调用 c++ 方法?

- (NSValue*)getExpression
{
    Expression* e = new Expression();
    return [[NSValue alloc] initWithPointer:e];
}

- (void)callExpression(NSValue*)expression
{
    Expression* e = [expression pointerValue];
    e->evaluate();
}
于 2021-01-17T11:41:06.393 回答