[C++] как явно отличить переопределение виртуального метода?

trobak

Имеется базовый класс, определяющий некую схему поведения, и куча потомков, реализующие детали этой схемы. Есть виртуальный метод, который определяет особенности реализации, причем в 90% случаев это один и тот же способ, потому делать этот метод абстрактным не хочется. Но в некоторых потомках этот метод надо переопределить.
Вот тут и начинается проблема - если я нечаянно не точно воспроизведу сигнатуру метода в базе, то будет ошибка. А ошибки вероятны, так как структура может меняться довольно динамично (например, добавление/удаление параметра, квалификатора const, изменение возвращаемого типа).
Хочется явно сказать: нужно именно переопределить метод потомка, а если такого метода у потомка нет, то пусть компилятор/линкер выдаст ошибку.
Есть ли какой-нибудь "изящный" способ это сделать?
 

class Base
{
//bla-bla-bla
virtual bool ToBeOrNotToBe const { return false; }
};

class Derived001 : public Base { /*bla-bla-bla*/ };
class Derived002 : public Base { /*bla-bla-bla*/ };

// ......................
class Derived289 : public Base
{
virtual bool ToBeOrNotToBe { return true; }
//wrong! Should be
//virtual bool ToBeOrNotToBe const { return true; }
};

pitrik2

в джава ввели @Override для этого

kokoc88

Есть ли какой-нибудь "изящный" способ это сделать?
Отделить интерфейс или абстрактный класс от базового класса.

struct abstract_base
{
virtual ~abstract_base { }
virtual void f const = 0;
};

class base : public abstract_base
{
public:
void f const;
};

evgen5555

делать этот метод абстрактным не хочется
Есть такое слово "надо" :)

trobak

Хорошая идея.
Правда, у меня таких виртуальных методов может быть несколько, а вводить по базовому классу для каждого подмножества виртуальных методов, работающих по умолчанию, как -то не хочется Ну, и делать иерархию классов слишком сложной тоже не очень хочется.
Но в простых случаях - то что надо! Спасибо :)

SPARTAK3959

А ваша IDE не поддерживает рефакторинг и не содержит команду для переопределения метода? Тогда пушной зверек идет к вам ;).

yroslavasako

Если сигнатура часто меняется, передавай её через темплат

erotic

Мб так:
 
class Base
{
//bla-bla-bla
virtual bool ToBeOrNotToBe const = 0;
};

bool Base::ToBeOrNotToBe const { return false; }


class Derived001 : public Base
{
bool ToBeOrNotToBe const { return Base::ToBeOrNotToBe; }
};
class Derived002 : public Base
{
bool ToBeOrNotToBe const { return Base::ToBeOrNotToBe; }
};

//--------------
class Derived289 : public Base
{
// error! abstract class!
bool ToBeOrNotToBe { return true; }
};

enochka1145

пусть компилятор/линкер выдаст ошибку
А предупреждений компилятор никаких не выдаёт? Ну, в духе "Derived::ToBeOrNotToBe hides Base::ToBeOrNotToBe"?
Или пофиг на всякие там warning-и тупорылого компилятора?

kokoc88

А предупреждений компилятор никаких не выдаёт? Ну, в духе "Derived::ToBeOrNotToBe hides Base::ToBeOrNotToBe"?
Мы, несчастные Си++сники, не нужны нашему компилятору. Зато он делает ровно то, что мы попросим. И ничего более. :grin:

erotic

А предупреждений компилятор никаких не выдаёт? Ну, в духе "Derived::ToBeOrNotToBe hides Base::ToBeOrNotToBe"?
В gcc для этого надо опцию -Woverloaded-virtual прописать, иначе не будет.

enochka1145

Наверно, я резковато выразился в предыдущем посте, но пренебрежительное отношение к warning-ам на работе задрало.
А ведь серьёзные пацаны от C++ предупреждают: не игнорируйте warning-и!
Блин, что же это за отстойный такой компилятор - gcc... :(
stricmp там нет, strrev - тоже, теперь вот выясняется, что и на сокрытие имён базового класса ему пофиг. Хорошо хоть, есть полная интеграция с (отстойным) ассемблером.

erotic

Блин, что же это за отстойный такой компилятор - gcc... stricmp там нет, strrev - тоже
Это лишь говорит об отстойности стандартной библиотеки, а не компилятора.

slonishka

strcasecmp(3) LOL

sergeikozyr

Блин, что же это за отстойный такой компилятор - gcc... :(
stricmp там нет, strrev - тоже, теперь вот выясняется, что и на сокрытие имён базового класса ему пофиг. Хорошо хоть, есть полная интеграция с (отстойным) ассемблером.
это не гецеце, а цепепе - говно. Библиотечку то нормальную надо было делать, а не то что сейчас.

enochka1145

> strcasecmp(3) LOL
Спасибо, в курсе. Просто не ожидал от него в своё время такой подставы.

enochka1145

это не гецеце, а цепепе - говно. Библиотечку то нормальную надо было делать, а не то что сейчас.
Язык развивался со временем. Нормальная сейчас библиотека. Сам язык по критерию универсальность/эффективность/удобство рвёт всех в щепки.
Или нет?

Helga87

Или нет?
Нет.
Особенно по критерию удобство.

trobak

не, не выдает (MSVS 2005)
у меня отношение к ворнигам:"warning == error", так что если б знать, "где галочку поставить",чтобы хотя бы ворниг выскакивал - было б уже не плохо
хотя, генерация ошибки компиляции было б сильно желательнее, поскольку при компиляции (не полный ребилд) большого проекта ворниги выдаются только по "первому разу" для файла
в моей же ситуации нежелательные виртуальные методы возможны в разных файлах, а потому на ворнинги полагаться не надежно
ну ладно, для меня рулят чисто абстрактные методы, переопределенные в частично настроенных базовых классах, как советовал

trobak

Оно конечно правильно и грамотно, но вот при изменении сигнатуры базового метода (что у меня вполне реально придется лазить по 90% дефолтных классов и менять сигнатуру этого метода
можно конечно на макрос посадить дефолтное задание метода
#define TO2BORNOT2B bool ToBeOrNotToBe const { return Base::ToBeOrNotToBe; }
но тут, имхо, применения макроса не оправданно
(предпочитают избегать макросы "до последнего")
буду действовать, как советовал

yroslavasako

Как часто добавляются потомки? Если у тебя жесткая структура наследования, то можно юзать инспектора

trobak

вполне могут добавляться по ходу дела, причем могут добавляться и в другой библиотеке (не в той, в которой база определена)
у меня такой вопрос периодически возникает
то есть мне надо не любой ценой понять, что делать для конкретной иерархии, а скорее понять, как правильно поступать "на будущее"
289 классов потомков - я конечно слегка преувеличил :), но мне лично уже и в три "дефолтных" класса лезть и заниматься там копи-пастом противно

yroslavasako

289 классов потомков
а сколько примерно различных вариантов реализации этой функции?

trobak

у текущей иерархии у меня 8 классов потомков с поведением по умолчанию
вариант по умолчанию 1 (всегда возвращать false)
недефолтное поведение уже зависит от класса

Andbar

например, добавление/удаление параметра, квалификатора const, изменение возвращаемого типа
А разве VisualAssist'овский рефакторинг при изменении сигнатуры метода, не меняет сигнатуру методов в классах-наследниках?

trobak

да помогли мне уже :)
>VisualAssist'овский рефакторинг
подозреваю, что он все может :)
но как-то привык я по старинке "руками" исходники править
а потом - не надежно это как-то... Например, class view (уж не знаю чья эта фича VA-овская или встроенная VS-ного IntellSens-а (или как его зовут не показывает наследников класса в другой библиотеке, спотыкается на неймспейсах, подцепляет давно не открываемые проекты (откуда он хоть помнит их? честно жал всякие кнопочки очистки БД в VA)
уж молчу, что просто часто виснет (и приходится мочить файл с БД символов и т.д. и т.п.
так что, (сугубо ИМХО) VA - конечно, хороший и удобный инструмент (отставляя в стороне дискуссию то, что на него подсаживаешься, и без подсказки имен и сигнатур кодить заметно тяжелее но не надежный
Оставить комментарий
Имя или ник:
Комментарий: