В C ++ возможно ли использовать CRTP с частной базой? - PullRequest
0 голосов
/ 15 февраля 2019

В 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, тогда downcast не скомпилируется (недоступная база).Я мог бы заменить его на reinterpret_cast, тривиальный пример сработал бы, но reinterpret_cast не будет работать правильно, если есть множественное наследование, которое может быть в общем случае.

Есть ли простой способчтобы делать такие вещи?

Спасибо!

Редактировать: я должен добавить немного фона.Я пытаюсь писать в стиле, который использует протоколы, где это возможно, а не абстрактные суперклассы.Если бы я создал абстрактный суперкласс с публичным get_name () и защищенным print_name (), я мог бы легко заставить все работать.Проблема в том, что я не хочу абстрактный суперкласс.У него было бы несколько подклассов, с которыми я хотел бы быть не связанными (потому что я в конечном итоге хочу составить их, используя миксины или MI).

Моя идея состоит в том, что я буду составлять конкретный класс, и где-нибудь в этом классе или всуперкласс, что-то будет реализовывать get_name ().Этот конкретный класс будет нуждаться в наборе служебных функций, но эти служебные функции не должны быть частью интерфейса.

1 Ответ

0 голосов
/ 15 февраля 2019

Да, вы можете.Просто сделайте своего базового класса 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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...