2010-04-19 4 views
6

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

ответ

1

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

0

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

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, интерфейс ABCpublic действительно будет недоступен через D, потому что вы не смогли бы к базовому типу ABC. А если woof и moo были virtual, вам нужно сделать переопределения private, чтобы скрыть их. Возможно, это лучше отвечает на вопрос.

+1

Я уверен, что это имеет большое значение, если они были «частными» в классе ABC. 'class D' должен иметь доступ к базовым членам, прежде чем он сможет их успешно назвать в объявлении' using'. OTOH, они могли быть «защищены» в «ABC», и использование все равно будет работать. –

+0

@Ben: Извините, я имел в виду защищенный. Исправлена. – Potatoswatter

5

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

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

Пример:

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; 
} 

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

main.c: 7: ошибка: 'недействительными Foo :: private_member()' является частным

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

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

Смежные вопросы