CRTP - Могу ли я сделать частный метод? - PullRequest
1 голос
/ 26 мая 2019

Я реализую статический полиморфизм:

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 () снова был закрытым. Можно ли это сделать?

UPDATE: Я не хочу писать

friend class Base<Derived>;

в классе Derived, поскольку он предоставляет базовый доступ всем членам Derived.

1 Ответ

3 голосов
/ 26 мая 2019

Добавление строки к вашему 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();
    }
};

...