這是一個使用 Xcode 版本 13.2.1 創建的 Objective-C macOS 專案。在專案內部,我有一個名為“plistModifier”的模板類。該類旨在為任何 plist(例如NSString,NSNumber等)設定自定義型別的值。該類的頭檔案名為“plistModifier.h”,如下所示:
#ifndef plistModifier_h
#define plistModifier_h
#include <iostream>
#include <string>
#import <Foundation/Foundation.h>
#include <unistd.h>
template <class type>
class plistModifier {
public:
void modifyPref(std::string key, type value);
type getPref(std::string key);
};
#endif /* plistModifier_h */
該類的實作如下在一個單獨的“plistModifier.mm”檔案中:
#include "plistModifier.h"
template <class type>
void plistModifier<type>::modifyPref(std::string key, type val) {
NSString* preferencePlist = [[[NSBundle mainBundle] resourcePath] stringByAppendingString:@"/com.rA9.LeetDownPreferences.plist"];
NSDictionary* dict=[[NSDictionary alloc] initWithContentsOfFile:preferencePlist];
[dict setValue:val forKey:[NSString stringWithUTF8String:val]];
[dict writeToFile:preferencePlist atomically:YES];
}
template <class type>
type plistModifier<type>::getPref(std::string key) {
NSString *preferencePlist = [[[NSBundle mainBundle] resourcePath] stringByAppendingString:@"/com.rA9.LeetDownPreferences.plist"];
NSDictionary *dict=[[NSDictionary alloc] initWithContentsOfFile:preferencePlist];
return dict[key];
}
問題是,當我創建一個 plistModifier 物件并呼叫它的方法時,編譯器會拋出錯誤Undefined symbols for architecture x86_64: "plistModifier<int>::modifyPref(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, int)", referenced from: -[SettingsVC debuggingToggle:] in SettingsVC.o
這就是我在SettingsVC.mm檔案中呼叫物件方法的方式:
#import "SettingsVC.h"
#include "plistModifier.h"
plistModifier<int> plistObject;
- (IBAction)debuggingToggle:(id)sender {
plistObject.modifyPref("DebugEnabled", _debugToggle.state);
}
我曾嘗試在一個空的 C 專案中使用相同的模板類,但它沒有給我任何錯誤。你認為問題是什么?
uj5u.com熱心網友回復:
不能拆分模板宣告 (.h) 和定義 (.mm/.cpp)。您必須將模板方法實作保留在 .h 檔案中。
參考這個解釋
https://isocpp.org/wiki/faq/templates#templates-defn-vs-decl
但是由于您的實作沒有使用泛型型別type屬性,您可以通過在 .mm 中的id型別實作它來拆分它,然后在 .h 檔案中添加模板化包裝器:
// .mm
void plistModifierImpl::modifyPref(std::string key, id val) {
NSString *preferencePlist = [[[NSBundle mainBundle] resourcePath] stringByAppendingString:@"/com.rA9.LeetDownPreferences.plist"];
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:preferencePlist];
[dict setValue:val forKey:[NSString stringWithUTF8String:val]];
[dict writeToFile:preferencePlist atomically:YES];
}
// .h
class plistModifierImpl; // define this in .mm
template <class type>
class plistModifier {
// private loosely-typed implementation
std::unique_ptr<plistModifierImpl> p_impl;
public:
// public strongly-typed wrapper
void modifyPref(std::string key, type value) {
p_impl->modifyPref(key, value);
}
...
}
只要type可以隱式轉換為id,這就是有效的,對于 NSString、NSNumber、NSDate、NSArray 和 NSDictionary 都是如此。
如果您需要支持原始型別,例如int,則需要使用調整后的實作來專門化模板。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/426057.html
