在C ++中,可以将CRTP与私有库一起使用吗?

时间:2019-02-15 03:43:05

标签: c++ crtp downcast static-cast private-inheritance

在C ++中,我有许多类(通过继承无关)定义了方法std::string get_name() const

根据get_name()实现了许多类需要的几个实用程序函数。我希望实现get_name()的类也获得这些实用程序功能。举一个愚蠢的例子,假设对于每个具有get_name的类,我都想拥有void print_name() const { std::cout << get_name() << std::endl; }。但是,有一些这样的函数,我不想在每个需要它们的类中重复它们。

听起来像CRTP的工作

template <class T>
class NameMethods {
public:

  void print_name() const {
     std::cout << static_cast<const T&>(*this).get_name() << std::endl;
  }

};

效果很好。

这是折纸-如果我希望print_name()在子类中是私有的怎么办?如果子类从NameMethods私有继承,则向下转换将不会编译(不可访问的基础)。我可以用reinterpret_cast代替它,这是一个简单的示例,但是如果存在多重继承(通常情况下可能存在),则reinterpret_cast不会做正确的事情。

有没有一种简便的方法来做这种事情?

谢谢!

编辑:我应该添加一些背景。我试图以一种尽可能使用协议而不是抽象超类的风格来编写。如果使用公共get_name()和受保护的print_name()创建抽象超类,则可以轻松地使所有工作正常运行。问题是我不需要抽象超类。它会有几个我不想要的子类(因为我最终想使用mixins或MI来组成它们)。

我的想法是,我将组成一个具体的类,并在该类或超类中的某个位置实现get_name()。该具体类将需要一组实用程序功能,但这些实用程序功能不应成为接口的一部分。

1 个答案:

答案 0 :(得分:1)

是的,可以。 只需让您的CRTP基类成为您班上的朋友,向下转换将再次起作用:

template <class T>
class NameMethods {
public:

  void print_name() const {
     std::cout << static_cast<const T&>(*this).get_name() << std::endl;
  }

};

class MyClass: private NameMethods<MyClass>
{
public:
    std::string get_name() const { return "MyClass";}
    void get_info() const
    {
        print_name();
    }
private:
    friend class NameMethods<MyClass>;
};

int main()
{
    MyClass c;
    c.get_info();

    return 0;
}

查看实时示例:https://godbolt.org/z/5oQvSq