C++ 如何使用CRTP实现修复破坏强封装规则的问题?
我喜欢 但有时我想从NVI习惯用法中降低vftable成本。 然后我试着向NVI申请如下C++ 如何使用CRTP实现修复破坏强封装规则的问题?,c++,encapsulation,crtp,C++,Encapsulation,Crtp,我喜欢 但有时我想从NVI习惯用法中降低vftable成本。 然后我试着向NVI申请如下 template<typename E> class unary_interface { public: virtual ~unary_interface() = default; public: double operator()(const double x) const { return static_cast<const E&>
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;
}
};
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;
}
};
模板
类一元接口{
公众:
虚拟~一元_接口()=默认值;
公众:
双运算符()(常数双x)常数
{
返回static_cast(*this).apply(x);//发生编译错误!!!
}
};
类方:公共一元接口{
私人:
双应用(常数双x)常数
{
返回x*x;
}
};
但此代码发生编译错误
若我将private字段中的apply函数更改为public,封装就会被破坏。
我有一个想法,不透明别名解决这个问题如下
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;
}
};
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;
}
};
模板
类一元接口{
公众:
虚拟~一元_接口()=默认值;
受保护的:
类输入类型{
公众:
显式输入类型(const double x):\ux(x){}
运算符double()常量
{
返回x;
}
私人:
常数双x;
};
公众:
双运算符()(常数双x)常数
{
返回static_cast(*this).apply(输入_类型(x));
}
};
类方:公共一元接口{
使用基本类型=一元接口;
公众:
双应用(常量基本类型::输入类型和d)常量
{
const double x=静态施法(d);
返回x*x;
}
};
本设计一直禁止从一元_接口的运算符()访问应用函数
乍一看,“应用函数”是向用户代码公开的,但应用函数是仅接受受保护的不透明别名类型,它是在受保护字段的一元_接口上定义的。
我认为这种组合非常好,并且在保持强大封装的情况下降低了虚拟函数的成本
这个想法是否有我找不到的缺陷,你对这个设计有具体的名字吗
但此代码出现编译错误。…
乍一看,“应用函数”是向用户代码公开的,但应用函数是仅接受受保护的不透明别名类型,它是在受保护字段的一元_接口上定义的。我认为这种组合非常好,并且在保持强大封装的情况下降低了虚拟函数的成本 您可以使用
friend
(在这种情况下,它不会附带任何功能)轻松解决您的强封装难题:
class square:公共一元接口{
friend class一元_interface;//谢谢你的回复。我同意复杂的设计是不好的。起初,我有了使用friend的想法。我错误地认为friend总是不受欢迎的,但我认为friend在特定情况下是非常有效的工具,多亏了你。@YusukeMori很高兴能提供帮助。你可能需要为这个问题找到一个更好的标题。@YusukeMori打开。但一般来说,它是相当有用的。当您公开private
内部类句柄时,有一种不同的情况,它可以与public
API中的auto
一起使用。