【发布时间】:2015-02-28 13:56:48
【问题描述】:
在使用 Xcode4 构建可可应用程序时尝试混合 c++ 和 Objective-c 时遇到问题。 问题是当我使用 NSTimer 调用 handleFrame 函数时,它调用了一个类的虚函数。
这是我想要做的: 1.创建监视器; 2.创建处理程序; 3. 将处理程序分配给监视器(init 函数) 4. 调用monitor->update() 预期调用handler 的虚方法。 5. 代码在 applicationDidFinishLaunching 函数中按预期工作,但是 NSTimer 在 handleFrame 中导致 EXC_BAD_ACCESS 异常。
//
// AppDelegate.h
// Concept5
//
#import <Cocoa/Cocoa.h>
#include "monitor.h"
#include "Derived.h"
@interface AppDelegate : NSObject <NSApplicationDelegate>
{
Monitor *monitor;`enter code here`
NSTimer *gameTimer;
}
@property (assign) IBOutlet NSWindow *window;
- (void)handleFrame:(NSTimer *)timer;
@end
AppDelegate implementation (.mm)
//
// AppDelegate.mm
// Concept5
//
#import "AppDelegate.h"
@implementation AppDelegate
- (void)dealloc
{
[super dealloc];
}
- (id) init {
self = [super init];
if(self) {
monitor = new Monitor();
}
return self;
}
- (void)handleFrame:(NSTimer *)timer {
monitor->update();
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Insert code here to initialize your application
Derived derived;
monitor->init(derived);
monitor->update();
gameTimer = [[NSTimer scheduledTimerWithTimeInterval:1
target:self
selector:@selector(handleFrame:)
userInfo:nil
repeats:YES] retain];
monitor->update();
}
@end
//
// Monitor.cpp
// Concept5
//
#include "Monitor.h"
void Monitor::init (Base& handler)
{
_handler = &handler;
}
void Monitor::update()
{
if (_handler != NULL)
{
_handler->speak(); // <-- EXC_BAD_ACCESS exception.
}
}
//
// Monitor.h
// Concept5
#ifndef __Concept5__Monitor__
#define __Concept5__Monitor__
#include <iostream>
#include "Base.h"
class Monitor
{
private:
Base* _handler;
public:
void init (Base& handler);
void update();
};
#endif /* defined(__Concept5__Monitor__) */
//
// Base.cpp
// Concept5
#include "Base.h"
void Base::speak()
{
std::cout << "Base speaks" << std::endl;
}
//
// Base.h
// Concept5
#ifndef __Concept5__Base__
#define __Concept5__Base__
#include <iostream>
class Base
{
public:
virtual void speak();
};
#endif /* defined(__Concept5__Base__) */
//
// Derived.cpp
// Concept5
#include "Derived.h"
void Derived::speak()
{
std::cout << "Derived speaks" << std::endl;
}
//
// Derived.h
// Concept5
//
#ifndef __Concept5__Derived__
#define __Concept5__Derived__
#include <iostream>
#include "Base.h"
class Derived : public Base
{
public:
void speak();
};
#endif /* defined(__Concept5__Derived__) */
【问题讨论】:
-
更新:在 NSTimer 触发之前,_handler 类型是 Derived(预期),但在 NSTimer 触发之后,_handler 类型是 Base。
-
你有一个构造函数,它接受一个地址并存储它。在 init() 函数和 update() 函数之间的过渡期间,没有迹象表明该地址指向的内容发生了什么或发生了什么。然后在更新函数中测试 not NULL,但如果指向的对象无效,则该测试毫无价值。
-
可能是在 applicationDidFinishLaunching 中创建的派生对象超出范围并在 applicationDidFinishLaunching 完成时被销毁?并且它的引用没有被monitor的实例保留?
-
可能就是这个问题。我在下面发布了一个答案,尽管我不是 Objective-C 程序员。
标签: c++ objective-c xcode macos