【问题标题】:CRTP - Can I make a private method?CRTP - 我可以创建一个私有方法吗?
【发布时间】:2019-10-12 08:01:52
【问题描述】:

我正在实现一个静态多态性:

template<typename T>
class Base {
public:
    void method() {
         // do something
         impl();
         // do something else
    }
    void impl() { // intended to be private
        static_cast<T*>(this)->impl();
    }
};

class Derived : public Base<Derived> {
public:
     void impl() { // intended to be private
     }
};

这段代码是动态多态类的静态实现,其中 void impl() 是虚拟的和私有的。

我已经实现了多态性(静态)。但是我必须将方法 void impl() 公开,以便允许从基类访问它。我希望方法 void impl() 再次成为私有的。能做到吗?

更新: 我不想写了

friend class Base<Derived>;

在 Derived 类中,因为它允许 Base 访问 Derived 的所有成员。

【问题讨论】:

  • 您可以将friend class Base&lt;Derived&gt; 添加到Derived 类中。
  • 我认为这通常是过度设计,但如果您认为朋友船太多,您可以使用 attorney-client idiom 完善友谊。
  • 我附上了我的答案以反映您的建议,@Oliv

标签: c++ crtp static-polymorphism


【解决方案1】:

Derived 类中添加一行:

class Derived : public Base<Derived> {
public:
private:
     void impl() { // intended to be private
     }
     friend class Base<Derived>;
};

它将基类指定为朋友,允许我编译代码,impl 是私有的。

编辑

正如@Oliv 在评论中所建议的那样,“律师-客户”习语的实现如下所示:


template<typename T>
class Attorney;

template<typename T>
class Base {
public:
    void method() {
        // do something
        impl();
        // do something else
    }
private:
    void impl() { // intended to be private
        Attorney<T>::impl(*static_cast<T*>(this));
    }
};


class Derived : public Base<Derived> {
private:
    void impl() { // intended to be private
    }
    friend class Attorney<Derived>;
};

template<typename T>
class Attorney {
private:
    friend class Base<Derived>;

    static void impl(Derived & c) { // add additional parameters as needed by impl
        c.impl();
    }
};

【讨论】:

  • 谢谢!但是这个解决方案是不是太强了?现在 Base 可以访问 Derived 的所有成员。
  • 虽然我不确定如何只公开impl,但我怀疑这里使用 crtp 的设计只需要一个方法应该是私有的,而不是其余的,所以在实用性上不会被应用。
  • 在这种情况下,一种更透明的潜在设计是创建两个 crtp 类,一个需要访问私有方法,另一个不需要。
  • @stephematician 而不是一般地定义它?当试图将 Base::impl 暴露给 Deriv::impl 时,在这里按名称使用 Derived 类是一个直接的解决方案,并且不再做任何事情。虽然,它可以用于一般派生类型 T,这是给定的。
  • Attorney 可以是一个嵌套类,这里的示例只是反映了人们可能在 wikipedia 上找到的所有示例实现等。如果律师对所有人可见,则需要私有访问但不派生的类也可以拨打impl。嵌套会改变的一件事是将朋友声明更改为Base&lt;T&gt;::Attorney
猜你喜欢
  • 2019-04-04
  • 2015-04-01
  • 2014-08-02
  • 2022-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-20
  • 2022-09-27
相关资源
最近更新 更多