我想撰寫一個函式,它以特定順序f呼叫派生類的兩個被覆寫的虛擬方法op_1和,而不會暴露這些方法以及方法的包含類。op_2f
我可以想到一些可行或幾乎可行的方法,但我也是 C 新手,希望在常規性、可維護性等方面選擇“最佳”方式的幫助:
- 創建一個按順序呼叫虛擬操作
f的基類 ( ) 的公共非虛擬方法,并將操作設為私有。Base
/***** .h *****/
class Base {
virtual void op_1() const = 0;
virtual void op_2() const = 0;
public:
void f();
};
/***** .cpp *****/
void Base::f() {
op_1();
op_2();
}
- 公開操作并公開非成員非朋友助手以按順序呼叫它們。
/***** .h *****/
struct Base {
virtual void op_1() const = 0;
virtual void op_2() const = 0;
};
void f(const Base& b,) {
b.op_1();
b.op_2();
}
- 將操作保留為私有并公開一個友元函式以按順序呼叫它們。
/***** .h *****/
class Base {
virtual void op_1() const = 0;
virtual void op_2() const = 0;
friend void f(const Base& b);
};
void f() {
b.op_1();
b.op_2();
}
#1 seems bad because derived classes also have access to f, but it's not intended or useful for them and could be misused.
#2 resolves that, but is less encapsulated because the ops are public.
#3 seems to resolve both concerns, but I'm new to C and standoffish about friending things - it seems to muddle interfaces and the guidance I've read (e.g. Effective C #23) discourages its use without clear need. Is this an appropriate case for it?
#4 ??? Probably there's a better way I can't see. Enlighten me!
App-specific context, in case you want the "Why"
I need to register some data types with a 3rd party data store on app initialization - there are 2 synchronous operations I need to perform in order:
store.data_type<MyAppDataType>()adds a table for an app-specific data type to the store.store.data_type<MyAppDataType>().member<MemberDataType>("member_name")yields the app-specific data type registered in step 1 and sets up one of its fields for use with the library's reflection APIs - useful for debugging in non-production builds.
Operation #2 is optional, but if performed it should occur after operation #1.
I want the various modules[1] of my application to register their own data with the store to avoid having a big messy file where all the data for the app is registered together. To do this, I am including a class in each module which extends a DataRegistrar base class - the base forces derived classes to provide module-specific implementations for the two operations above:
struct DataRegistrar {
virtual void register_data_types(lib::store& store) const = 0;
virtual void setup_reflection(lib::store& store) const = 0;
};
在應用程式的其他地方,我可以有一些在應用程式啟動時運行的代碼,它按順序為每個模塊呼叫register_data_types和。setup_reflection在簡化的問題中,以下是映射到上述方法的方法:
- (映射到上面的#1)
/***** .h *****/
class DataRegistrar {
virtual void register_data_types(lib::store& store) const = 0;
virtual void setup_reflection(lib::store& store) const = 0;
public:
void register_data(lib::store& store);
};
/***** .cpp *****/
void DataRegistrar::register_data(lib::store& store) {
register_data_types(store);
#if !PROD_BUILD
setup_reflection(store);
#endif
}
- (映射到上面的#2)
/***** .h *****/
struct DataRegistrar {
virtual void register_data_types(lib::store& store) const = 0;
virtual void setup_reflection(lib::store& store) const = 0;
};
void register_data(const DataRegistrar& module_registrar, lib::store& store) {
module_registrar.register_data_types(store);
#if !PROD_BUILD
module_registrar.setup_reflection(store);
#endif
}
- (映射到上面的#3)
/***** .h *****/
class DataRegistrar {
virtual void register_data_types(lib::store& store) const = 0;
virtual void setup_reflection(lib::store& store) const = 0;
friend void register_data(const DataRegistrar& module_registrar, lib::store& store);
};
void register_data(const DataRegistrar& module_registrar, lib::store& store) {
module_registrar.register_data_types(store);
#if !PROD_BUILD
module_registrar.setup_reflection(store);
#endif
}
[1] 應用程式的區域/目錄/域中的“模塊”,而不是 c 20 模塊
uj5u.com熱心網友回復:
讓我們從#3開始:
friend打破封裝,這就是 Scott Meyers 不建議這樣做的原因。我也不建議,除非你真的需要它。例如:CRTP 的私有構造 朋友技巧,以防止拼寫錯誤。
我建議#1,因為所有作業都是由擴展 inerface 的類完成的DataRegistrar。另外,您不希望其他人擺弄op_1()and op_2()。
如果使用自由函式,則要求實體有op_1()和op_2()被暴露,增加了被誤用的機會。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/453139.html
上一篇:處理靜態變數時的棘手繼承問題
