Остановка наследования из базового класса после n-го наследования в C ++ - PullRequest
0 голосов
/ 07 января 2019

У меня есть проблема, когда мне нужно наследовать базовый класс только один раз. После этого я хочу, чтобы никто не унаследовал этот класс. Может кто-нибудь объяснить мне, как этого можно достичь. Более того, если количество наследуемых базовых классов равно n раз (например, 1 .. 10), то это будет общий способ сделать это.

Я знаю, что использование класса друга в базовом классе может в некоторой степени решить мою проблему. Но я нахожу это неуклюжим. Также я прочитал о Ограничить наследование желаемым количеством классов во время компиляции . Я не смог понять ответ полностью.

Может кто-нибудь предложить мне более эффективные способы ограничения наследования во время компиляции в c ++.

Ответы [ 3 ]

0 голосов
/ 07 января 2019

В настоящее время базовый класс наследуется внутренней командой. Теперь этот класс доступен третьей стороне. Однако я не хочу, чтобы они унаследовали этот базовый класс. Так что это постановка проблемы

Проблема в том, что C ++ не предоставляет никаких средств для прямого ограничения наследования таким образом.

Указатель на идиому реализации может в любом случае помочь вам обойти:

class PublicToUser final
{
    class PrivateToUser;
    std::unique_ptr<PrivateToUser> implementation;
public:
    // ***
};

Теперь это будет частный внутренний класс, который на самом деле наследует, но это может быть полностью скрыто, т.е. е. вам вообще не нужно предоставлять этот базовый класс пользователю & ndash; то, что не видно, не будет унаследовано ...

0 голосов
/ 08 января 2019

Вот некоторые идеи, которые могут помочь, если вы не можете использовать решение PIMPL из другого ответа. Они либо основаны на CRTP, либо на тегах конструктора:

#include <type_traits>

struct A;

template<typename T>
struct Base final {

};

// Specialise Base for A to be non-final
template<>
struct Base<A> {};

struct A : Base<A> {};

Идея первого фрагмента состоит в том, чтобы иметь final CRTP-базу и добавить нефинальную специализацию для класса A. Очевидно, что это позволяет пользователям (или вам самим) определять больше разрешенных производных, если это необходимо, но предотвращает случайное наследование.

template<char...>
struct password {};

struct Base2 {

    Base2() = delete;

    template<char... pwd>
    Base2(password<pwd...> ) {
        using expected_pwd = password<'t','o','p','s','e','c','r','e','t'>;
        static_assert(std::is_same_v<password<pwd...>, expected_pwd>);
    }
};

struct A2 : Base2 {

    A2() : Base2(password<'t','o','p','s','e','c','r','e','t'>{}) {}
};

struct A3 : Base2 {

    // No way to construct Base2 without correct password :)
    A3() : Base2(password<'b', 'a', 'm', 'm'>{}) {}
};

Идея этого второго фрагмента (который больше шутит, чем реальный код ...) состоит в том, чтобы заменить конструктор по умолчанию класса Base2 структурой password. В рамках реализации вы проверяете пароль, данный конструктору. В реализации вашего производного класса вы просто вызываете конструктор Base2 с правильным паролем. Конечно, ваши пользователи могут наследовать базовый класс, но так как пароль полностью скрыт в реализации, нет способа создать производные объекты:)

int main(){

    auto a = A{};
    auto a2 = A2{};
    auto a3 = A3{};  // fails
    return 0;
}
0 голосов
/ 07 января 2019

У меня проблема с тем, что мне нужно наследовать базовый класс только один раз. После этого я хочу, чтобы никто не унаследовал этот класс.

Начиная с C ++ 11, вы можете просто использовать final для предотвращения дальнейшего подкласса класса:

class BaseClass { };

class DoNotInheritClass final : public BaseClass { };

Для ограничения количества подклассов из одного базового класса, по-видимому, нет встроенной функции C ++. Вы должны следить за подклассами самостоятельно, добавив некоторую статическую переменную. Вот существующий ответ: Подсчет экземпляров отдельных производных классов

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