Доступ к спецификатору при переопределении методов - PullRequest
7 голосов
/ 20 апреля 2010

Предположим, у вас есть класс, который определяет виртуальные методы со спецификатором доступа public. Можете ли вы изменить спецификатор доступа в ваших переопределенных методах? Я предполагаю нет. Ищу объяснения.

Ответы [ 4 ]

6 голосов
/ 20 апреля 2010

Ответ: вроде. Вы можете изменить только доступ членов, к которым имеет доступ производный класс. Тип наследования не имеет никакого эффекта - он контролирует доступ по умолчанию только для унаследованных членов (до точки, соответствующей другим правилам).

Таким образом, вы можете сделать защищенных членов базового класса общедоступными или закрытыми; или открытые члены базы защищены или частные. Однако вы не можете сделать частных членов базы общедоступными или защищенными.

Пример:

class Foo
{
protected:
        void protected_member();

private:
        void private_member();

public:
        void public_member();
};

class Bar : private Foo
{
public:
        using Foo::protected_member;
        using Foo::private_member;
        using Foo::public_member;
};

int main(int, const char**)
{
        Bar bar;

        return 0;
}

Приведенный выше код вызывает следующую ошибку на g ++ 4.1.2:

main.C: 7: ошибка: void Foo :: private_member () 'является приватным

main.C: 14: ошибка: в этом контексте

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

4 голосов
/ 20 апреля 2010
2 голосов
/ 20 апреля 2010

Вы определенно можете. Но это не имеет смысла. Если это публичное наследование, то вы всегда можете привести объект к его базе. Если это частное наследование, все базовые методы по умолчанию уже закрыты. В случае защищенного наследования вы можете сделать базовый метод закрытым, чтобы предотвратить вызов его возможными производными классами, но я не совсем понимаю, зачем он нужен.

0 голосов
/ 20 апреля 2010

Да, вы можете, и на самом деле вам даже не нужно переопределять или использовать что-либо виртуальное.

class ABC {
public: // or this may be protected, no difference
    void woof();
    void moo();
};

class D : private ABC { // now woof and moo are private
public:
    using ABC::woof; // using declaration to make woof public again
    ABC::moo; // access declaration (deprecated) does the same
};

То же самое работает, если они тоже виртуальные. Или, как отмечали другие, поиск виртуальных функций игнорирует доступ, указанный реализующим классом; любой класс, к которому вы можете привести, может предоставить доступ во время компиляции.

С другой стороны, без специальных объявлений в D интерфейс public для ABC действительно был бы недоступен через D, потому что вы не смогли бы выполнить повышение до ABC. И если бы woof и moo были virtual, вы бы хотели сделать переопределения private, чтобы скрыть их. Возможно, это лучше отвечает на вопрос.

...