我喜歡NVI idiom。如何解決使用CRTP實現破壞強封裝規則?
但有時我想從NVI成語中減少vftable成本。 然後我嘗試將CRTP應用於NVI,如下所示。
template<typename E>
class unary_interface {
public:
virtual ~unary_interface() = default;
public:
double operator()(const double x) const
{
return static_cast<const E&>(*this).apply(x); //occurs compile error!!!
}
};
class square : public unary_interface<square> {
private:
double apply(const double x) const
{
return x * x;
}
};
但出現此代碼編譯錯誤。
如果我在私有領域中將應用函數改爲public,則封裝被破壞。 我有一個不透明的別名解決這個問題的想法如下。
template<typename E>
class unary_interface {
public:
virtual ~unary_interface() = default;
protected:
class input_type {
public:
explicit input_type(const double x) : _x(x) {}
operator double() const
{
return _x;
}
private:
const double _x;
};
public:
double operator()(const double x) const
{
return static_cast<const E&>(*this).apply(input_type(x));
}
};
class square : public unary_interface<square> {
using base_type = unary_interface<square>;
public:
double apply(const base_type::input_type& d) const
{
const double x = static_cast<const double>(d);
return x * x;
}
};
本設計禁止訪問除unary_interface的operator()之外的apply函數。
乍一看「應用函數」暴露給用戶代碼,但apply函數僅接受保護字段中的unary_interface上定義的受保護的不透明別名類型。 我認爲這種組合非常好,通過保持強大的封裝來降低虛擬功能成本。
這個想法有什麼缺點,我找不到,你有這個設計的具體名稱?
感謝您的回覆。我同意複雜的設計是不好的。起初,我有使用朋友的想法。我錯誤地認爲朋友總是被棄用,但是我知道朋友是在特定情況下的高效工具,這要歸功於你。 –
@YusukeMori很樂於助人。您可能需要爲該問題找到更好的標題。但總的來說,這是相當有用的。當你公開'private'內部類_handles_時,可以使用'public''API中的'auto'。 –