c++ - функция - как в objective c объявить виртуальный и чисто виртуальный методы



Не чистые виртуальные функции с параметрами плохой практики? (7)

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

int func(int x)
{
   (void) x;
}

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

class Base {
    virtual void OnlyImplementThisSometimes(int x) {}
};

Когда я скомпилирую это, я получаю предупреждение о неиспользуемом параметре x. Есть ли другой способ, которым я должен был реализовать виртуальную функцию? Я переписал его так:

class Base {
    virtual void OnlyImplementThisSometimes(int x) 
    {
        x = 0;
    }
};

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

class Derived : public Base {
    void OnlyImplementThisSometimes(int x, int y) { // some code }
};

Derived d;
Base *b = dynamic_cast<Base *>(&d);
b->OnlyImplementThisSometimes(x); // calls the method in the base class

Метод базового класса был вызван, потому что я реализовал производную функцию с параметром «int y», но об этом нет предупреждений. Являются ли эти общие ошибки в C ++ или я неправильно понял виртуальные функции?


Answer #1

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


Answer #2

Игнорируя проблемы проектирования, вы можете обойти предупреждение компилятора о неиспользуемой переменной, опуская имя переменной, например:

virtual void OnlyImplementThisSometimes(int ) { }

Ошибочно внедрить неправильную подпись метода при попытке переопределить виртуальную функцию - это то, о чем вам нужно быть осторожным в C ++. Языки, подобные C #, обходятся с ключевым словом «переопределить».


Answer #3

Мы определяем макрос _unused как:

#define _unused(x) ((void)x)

Затем определите функцию как:

virtual void OnlyImplementThisSometimes(int x) { _unused( x );}

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


Answer #4

Это не плохая практика, и это распространенная идиома для указания частей класса, которые являются необязательными для реализации.

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

class mouse_listener{
public:
    virtual ~mouse_listener() {}

    virtual void button_down(mouse_button a_Button) {}
    virtual void button_up(mouse_button a_Button) {}
    virtual void scroll_wheel(mouse_scroll a_Scroll) {}
    virtual void mouse_move_abs(math::point a_Position) {}
    virtual void mouse_move_rel(math::point a_Position) {}
};

Answer #5

Это несколько распространено в моем коде. Например, у меня есть классы, которые предназначены для однопоточной работы и многопоточности. Существует множество общих подпрограмм и данных. Я поместил все это в базовый класс (который также имеет пару чистых виртуальных).

Я реализую две пустые виртуальные функции в базовом классе: Init () и Cleanup (). Однопоточный производный класс не влияет на них, но делает это с мулитной резьбой.

У меня есть заводская функция, создающая соответствующий производный класс, а затем возвращающий указатель. Клиентский код знает только тип базового класса и вызывает Init () и Cleanup (). Оба сценария поступают правильно.

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


Answer #6

Попробуй это:

class Base {
    virtual void OnlyImplementThisSometimes(int x) = 0;
};

Прошло некоторое время с тех пор, как я сделал такие вещи, но я верю, что так вы объявляете виртуальную функцию.

Также, как говорили другие, имена переменных необязательны в объявлениях функций, подобных этому.





polymorphism