[c++] кажется, я не понимаю как работает protected
разве нельзя вызвать защищенную (protected) функцию из потомка этого же класса?Нет, разумеется, в этом и смысл этого слова.
разве нельзя вызвать защищенную (protected) функцию из потомка этого же класса?Вызвать можно, через инстанциированный объект - нельзя.
class PreffixWriter : public COutWriter
{
protected:
void write(const string& s)
{
COutWriter::write("# "+s);
}
};
блин, и что делать?
Т.е., из реализации метода можно вызывать, а извне — нет.
Сделай их друзьями.
P.S. хотя как вариант лучше чем в паблик выставлять, спасибо
минус, за спойлер!
есть такой код, он не компилится (g++ 4.4.5)у вас проблема в дизайне и язык (компилятор) вам это подсказывает.
ошибка возникает на вызовах first.write и second.writeи правильно делает.
разве нельзя вызвать защищенную (protected) функцию из потомка этого же класса?вопрос неточен, поэтому отвечу прямо: так как вы написали делать нельзя
вот вероятно правильный ответ:
http://ideone.com/12Xor
ошибка дизайна: DualWriter наплевал на синхронизацию двух делегатов и пытался напрямую вывести строки
компилятор надавал а-та-та-та
вы рассуждаете логично, но стандарт ввел лично для меня непонятное ограничение.
Зачем точки с запятными здесь:
virtual void lock{};
virtual void unlock{};
?
Зачем вообще строчки
"private:"
и
"return 0;"
?
Почему в слове "PreffixWriter" всего 2 буквы "f"?
Почему в этом отрывке
StringWriter &second;
protected:
void write(const string& s)
один амперсанд слева, а другой - справа?
[зануда mode on]а меня больше всего забавляет имплементация метода syncWrite
вот так перешел в режим зануды навсегда...
Ну и потрындеть понятно, склонен.
Да уж, в XXI-м веке уже хочется, чтобы mutex-ы разблокировались автоматически в деструкторе.
"return 0;"а чем это-то не угодило?
private: многие пишут типа для большей наглядности
всё остальное да, странно выглядит
а чем это-то не угодило?типа в main можно не писать return
непубличным нужно делать то, что в будущем может исчезнуть или быть как-то совсем по-другому переписано, чтобы потом не искать все места, где заложились на старые предположения. а куда может исчезнуть метод write из класса с публичным методом syncWrite, или что можно в его семантике поменять, я не могу себе представить.
#define protected public
из соображений чтобы не вызывать искушение (или случайно) вызвать write без блокировок, ибо использоваться будет гарантировано в потоках.
[зануда mode on]
ну, слава Б-гу, а то я уж думал никто придираться не начнёт.
Но тут у нас непонимание в простом базовом вопросе - "как работает protected", так что я решил особо не зверствовать.
Почему, кстати? Если в c++ в классе по умолчанию права private, почему бы не начинать с них? С точки зрения синтаксиса более естественно. С другой стороны, для читателя декларации важнее увидеть сперва публичные и защищённые методы.
С другой стороны, для читателя декларации важнее увидеть сперва публичные и защищённые методы.Именно. А про экономию слов ТС уже приводил тут фееричнейший пример: он не повторяет virtual в наследниках, но писал комментарии, что мол эта функция перекрывает определенную в базовом классе...
Если бы я придирался, я бы обратил внимание на непоследовательность в использовании пробеловты обратил, правда это еще не значит, что придирался
не повторяет virtual в наследниках, но писал комментарии, что мол эта функция перекрывает определенную в базовом классенда, уж лучше тупо писать virtual везде в наследниках
вот вы прикопались, я комент к виртуальной функции писал только в том экзампле, то что я сделал что-то один раз не означает что я делаю это всегда. см. этот тред например.
так ты в этом треде не пишешь virtual все еще
а зачем его писать?
Ух ё-моё...
Да это вообще - расстрел на месте!
вот если бы было ключевое слово означающее перекрытие виртуальной функции а-ля override я бы его писал. но его нету. а virtual я воспринимаю больше как ввод новой виртуальной функции и если в перекрытии его написать мне кажется это будет запутывать.
// // расстрел на месте
... с конфискацией имущества и без права реабилитации!
Что это такое?
// но его нету
Нет - чего?
переопределение метода
//Нет - чего?
хз как у вас в сях - по дефолту(без директивы) методы виртуальные?
// перекрытие виртуальной функции а-ля override
Что это такое?
// но его нету
Нет - чего?
ты [/зануда mode on] сделай, а то на всю жизнь таким останешься
Нет, конечно. Более того, даже виртуальные методы уважающий себя компилятор будет пытаться девиртуализировать. Ибо если процессор умеет предсказывать ветвления - неплохо бы этим пользоваться, а не бежать куда-то смотреть фактический адрес функии.
Это нужно для дела. И уж лучше быть занудой, чем писать отстойный код для отстойных продуктов.
Мне вот за свою работу не стыдно.
мне чисто эстетически не нравится слово virtual в потомке у переопределяемой функции. потому что в этом месте оно имеет другой смысл, чем в месте первого появления виртуальной функции.
#define override virtual и то лучше
#define впринципе зло
Это какой же, позвольте узнать?
{
public:
virtual int f; // добавили в таблицу виртуальных функций класса новое вхождение
}
class D:public A
{
public:
virtual int f; // заменили указатель в таблице виртуальных функций на новый
}
{
public:
// Inherited from A
virtual int f; // заменили указатель в таблице виртуальных функций на новый
// Inherited from I
virtual void g; // опять грязно проигнорировали разумные, добрые, вечные идеи C#
}
а шарп тут причём?
Подозреваю, что override оттуда. Или из Java?.. Ну, где тебя насильно заставляют быть правильным и не дают права идти в ад собственной дорогой.
в яве ничего указывать не надо при переопределении.
я с override знаком из Delphi и вроде бы в раннем C++ оно тоже было, хотя в этом я не уверен.
а как в обозначениях си заслонить, или прервать VMT?
честно говоря, не знаю. но и придумать, когда это надо было бы не могу навскидку.
ни для чего хорошего, что нельзя бы было сделать без этого.
честно говоря, не знаю. но и придумать, когда это надо было бы не могу навскидку.версионность + децентрализованная разработка (когда предок и потомок модифицируются разными командами).
для B отнаследованного от A есть проблема в следующем сценарии:
сначала одна команда в B добавляет метод Problem
через некоторое время в A добавляется virtual метод Problem,
в итоге, B::Problem автоматически перекрывает метод A::Problem хотя это разные методы
изменить названия может быть проблемой, если уже есть куча стороннего кода.
ммм а интерфейсы на что?
ммм а интерфейсы на что?накладно (и по времени разработки, и по скорости работы) на каждый чих делать по интерфейсу
Наследственный класс имеет доступ к защищенным методам и данным базового класса, но не к защищенным методам и данным инкапсулированного объекта, разве что только это не один и тот же класс. Разница между объектом и классом, по-моему, очевидна.
Наследственный класс имеет доступ к защищенным методам и данным базового классавообще-то там доступ не к данным класса, а к данным экземпляра класса, на который ссылается this. Про то что this "равнее" других экземпляров - не очевидно.
Наследственный класс имеет доступ к защищенным методам и данным базового класса, но не к защищенным методам и данным инкапсулированного объекта, разве что только это не один и тот же класс.все с точностью до наоборот
курите маны!
З.Ы. а в сях есть такое исключение, что если предок и наследник объявлены в одном файле/юните(хз что там в сях то можно переопределять протектед?
а в сях есть такое исключение, что если предок и наследник объявлены в одном файле/юните(хз что там в сях то можно переопределять протектед?переопределять можно все, что является виртуальным. с протектед не связано никак. и с юнитами тоже
а в каком языке есть подобное "исключение" ?
он фигово сформулировал. в Дельфях есть такая багофича, что все протектед члены класса, объявленные в пределах одного модуля видны всем классам внутри этого модуля, т.е. в пределах одного unit protected = public.
я ошибся, там не переопределять, а вызывать должно быть, и не предка, а инкапсулированного объекта класса предок. и вообще не обязательно из наследника, а вообще любого класса/процедуры из того же юнита. бля, короче жгу.
бля, короче жгу.короче, нет ничего в C++
в c++ нету юнитов и их иногда не хватает, в основном из-за секций инициализации и деинициализации
з.ы где на ведроид клаве твердый знак?:)
в c++ нету юнитовчто вы подразумеваете под юнитами? в C++ есть translation unit, но вы явно что-то другое подразумеваете. в C++ нет модулей (пакетов) и это очень большой пробел, хотя он обусловлен спецификой самого языка
если долго жать мягкий - вылезает твёрдый
может на ведроиде так же
если долго жать мягкий - вылезает твёрдыйфцитаты
first.write(s);
это доступ к методу объекта (как ты выражаешься, экземпляру класса)
ClassName::write(s);
это доступ к методу класса
Класс — это абстракция, объект — память. Прошу понять.
DualWriter является наследником StringWriter, он имеет доступ к открытым и защищенным методам и данным базового класса (фактически, к своим). А first и second — это вставленные объекты. Ты имеешь право вызвать StringWriter::write, но не имеешь права вызвать first.write.
никакой здесь точности наоборот.
PS про this и равность экземпляров ничего не понял.
юнит - это в некошерном языке делфи сущность, которая по сути является pas-файлом, а на самом деле некий более мелкий контейнер чем пакет (в делфи аналогом пакетов являются bpl, или как во всех виндах ocx, dll, exe) компилятор компилит их каждый отдельно в dcu, после чего уже компонует пакет. внутри него немного отличаются некоторые стандартные правила ооп. также импорт/инклюды в делфи идет не пакетами, а юнитами. импорты транзитивны, т.е. в файле проекта/пакета который сам тоже юнит и там, куда его импортнут, будет видно всё, из чего он состоит. как тут уже отметили, имеет блок (де)инициализации, который вызывается при при загрузке rt-инфы в память. как-то так.
абстакция походу у вас в голове.
ClassName::write(s); - если write не статический, и эта запись внутри метода класса-наследника ClassName то это тоже обращение к методу объекта this. Чем отличается класс от объекта я знаю не хуже тебя.
как раз модули и подразумевал
Оставить комментарий
elenangel
есть такой код, он не компилится (g++ 4.4.5)ошибка возникает на вызовах first.write и second.write
разве нельзя вызвать защищенную (protected) функцию из потомка этого же класса?