Запретить внуку вызывать методы своего прародителя

#c #oop #inheritance

#c #ооп #наследование

Вопрос:

У меня есть простой родительский и базовый класс:

 class X
{
public:
 virtual void Method(){...}
};

class Z : public X
{
public:
 virtual void Method(){ X::Method(); }
};
 

Я хочу реорганизовать это, чтобы новый класс Y находился между ними в иерархии классов, так Z : Y Y : X что. Z::Method() теперь должен вызывать Y::Method() not X::Method() . Но если я не изменю это, он все равно компилируется. По правде говоря, у меня много таких методов, и очень легко пропустить вызов X::... при рефакторинге, что приведет к труднодоступным ошибкам.

Есть ли способ заставить компилятор предупредить меня, другими словами, сделать X методы доступными Y , но скрытыми от Z ?

Чтобы уточнить, это может быть только временное изменение, пока я выполняю рефакторинг, чтобы убедиться, что я ничего не пропустил.

Комментарии:

1. Обычный ответ: состав? Или частное наследование? Может быть, немного контекста было бы неплохо, зачем вам это нужно.

2. @idmean но затем Y необходимо реализовать сквозные методы для каждого метода, который в X нем не переопределяет …?

3. Итак, вы хотите, чтобы Y переопределял методы из X таким образом, чтобы Z больше не мог их вызывать. Я правильно понял?

4. Если вы хотите X , чтобы методы были доступны Y , но скрыты от Z , вы можете изменить их с public на private на, но создать Y friend класс. Я бы не советовал оставлять это так навсегда, но если ваша цель — избавиться от такого поведения, это будет иметь такой эффект.

5. @idmean нет, я хочу убедиться, что все места Z , в которых вызывается метод суперкласса X , обновлены для вызова Y .

Ответ №1:

Но если я не изменю это, он все равно компилируется. По правде говоря, у меня много таких методов, и очень легко пропустить вызов X:: … при рефакторинге, что приведет к труднодоступным ошибкам.

Чтобы уточнить, это может быть только временное изменение, пока я выполняю рефакторинг, чтобы убедиться, что я ничего не пропустил.

Поскольку вы описываете «при рефакторинге», вы можете временно добавить неполный тип X Z , который затеняет суперкласс X вверх по иерархии:

 class Z : public Y {
private:
    struct X;  // TODO(Mr. Boy): remove after finishing re-factoring.
public:
    void Method() override { X::Method(); }  // error! Z::X is incomplete
};
 

Любое квалифицированное использование X::... in Z завершится неудачей, поскольку поиск преобразуется в неполный вложенный тип X .