【问题标题】:Protected destructor of policy Classes in C++C++ 中策略类的受保护析构函数
【发布时间】:2013-05-18 02:55:50
【问题描述】:

我编写了以下愚蠢的策略结构:

template
<typename T>
struct SuperLeague
{
public:
  void printLeague(){std::cout << "SuperLegue" << std::endl;};
protected:
  //~SuperLeague(){}
};

和宿主类

template
<typename TT,template <typename C> class Policy>
class League: public Policy<TT>
{
public:
  void fun()
  {
    Policy<TT>().printLeague();
  }
};

我的主要是

int main()
{
  League<int,SuperLeague> k;
  League<int,SuperLeague> kk;
  k.fun();
  kk.printLeague();
  League<int,SuperLeague> *kkk=new League<int,SuperLeague>();
  kkk->fun();
  //delete kkk;
};

到这里为止,一切正常。输出是:

SuperLegue
SuperLegue
SuperLegue

安德烈·亚历山德雷斯库在他的一本书中写道: 除非策略类定义了虚拟析构函数,否则对指向策略类的指针应用删除具有未定义的行为。他解释了在从策略类派生时不在策略上使用虚拟析构函数或受保护(或私有)继承的原因,他建议 策略应该使用的轻量级、有效的解决方案是定义一个非虚拟保护析构函数。问题是当我尝试使用~SuperLeague(){} 执行此操作时,编译器会抱怨析构函数受到保护。我做错了什么?

【问题讨论】:

    标签: c++ templates destructor


    【解决方案1】:

    您不应该在 League::fun() 中创建临时策略对象。由于您的 League 模板实例派生自 Policy 模板的适当实例,因此它继承了 printLeague() 函数:

    template
    <typename TT,template <typename C> class Policy>
    class League: public Policy<TT>
    {
    public:
      void fun()
      {
        Policy<TT>::printLeague();
    //  ^^^^^^^^^^^^^^^^^^^^^^^^^^
      }
    };
    

    在声明析构函数protected 时解决方案无法编译的原因是protected 在访问对象(或取消引用指向对象的引用或指针)时使派生类可访问基类成员同一个派生类(在您的情况下为League)。

    在您的示例中并非如此,您创建了一个Policy&lt;TT&gt; 类型的临时对象并在该对象上调用printLeague() (它不是League 类型)。

    根据 C++11 标准的第 11.4/1 段:

    当非静态数据时,应用超出第 11 条中所述的附加访问检查 成员或非静态成员函数是其命名类 (11.2) 的受保护成员。如所述 早些时候,授予对受保护成员的访问权限是因为引用发生在某个朋友或某个成员中 C 类。如果访问要形成指向成员的指针(5.3.1),则嵌套名称说明符应表示 C 或 从 C 派生的类。所有其他访问都涉及(可能是隐式的)对象表达式(5.2.5)。 在这种情况下, 对象表达式的类应为 C 或从 C 派生的类

    【讨论】:

      【解决方案2】:
      Policy<TT>().printLeague();
      

      这会创建一个Policy&lt;TT&gt; 类型的对象,在该对象上调用printLeague(),然后销毁该对象。编译器抱怨要销毁对象,因为析构函数是受保护的。

      由于Policy&lt;TT&gt;是基类,直接调用printLeague()即可。

      【讨论】:

        猜你喜欢
        • 2011-05-30
        • 2013-11-03
        • 2012-06-04
        • 1970-01-01
        • 2011-03-15
        • 1970-01-01
        • 2012-11-23
        • 2020-03-06
        • 1970-01-01
        相关资源
        最近更新 更多