переопределение C ++ не работает как ожидалось [дубликат]

Квасной прав; триггер был бы лучшим способом для этого.

Вот код:

  СОЗДАТЬ ИЛИ ЗАМЕНИТЬ ФУНКЦИЮ ensce_photo_count () RETURNS trigger AS $$ DECLARE max_photo_count INTEGER: = 10  ;  photo_count INTEGER: = 0;  must_check BOOLEAN: = false;  BEGIN IF TG_OP = 'INSERT' THEN must_check: = true;  END IF;  IF TG_OP = 'UPDATE' THEN IF (NEW.owner! = OLD.owner) THEN must_check: = true;  END IF;  END IF;  IF must_check THEN - предотвращать одновременные вставки из нескольких транзакций LOCK TABLE photos В ЭКСКЛЮЗИВНОМ РЕЖИМЕ;  SELECT INTO photo_count COUNT (*) FROM photos WHERE owner = NEW.owner;  IF photo_count & gt; = max_photo_count ТОГДА ИСКЛЮЧЕНИЕ ПОДЪЕМА «Невозможно вставить больше, чем% фотографий для каждого пользователя.», Max_photo_count;  END IF;  END IF;  ВОЗВРАТ НОВЫЙ;  КОНЕЦ;  $$ LANGUAGE plpgsql;  CREATE TRIGGER enforce_photo_count ПЕРЕД ВСТАВКОЙ ИЛИ ОБНОВЛЕНИЕМ НА ФОТОГРАФИЯХ ДЛЯ КАЖДОЙ ПРОЦЕДУРЫ ROW EXECUTE enforce_photo_count ();   

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

0
задан Andrew WC Brown 4 December 2014 в 20:09
поделиться

2 ответа

В C ++ вам нужно специально объявить функцию как virtual:

class BaseClass {
    virtual void speak () {
        ...
    }
};
3
ответ дан Ying Xiong 16 August 2018 в 14:28
поделиться

В C ++ метод можно переопределить, если он был отмечен virtual. Вы можете думать о virtual как синониме «overridable».

Ключевое слово virtual должно появиться в базовом классе. Он также может появиться необязательно в подклассах в точке переопределения, но это не обязательно.

Если вы используете компилятор, который поддерживает C ++ 11 (и вы должны, если вы изучаете C ++) , Я рекомендую вам всегда использовать новое ключевое слово override, когда вы хотите переопределить:

class Base {
public:
    virtual void speak() {
        std::cout << "Base";
    }
};

class Derived : public Base {
public:
    void speak() override {  // <---
        std::cout << "Derived";
    }
};

Если этот метод не является переопределением, компилятор скажет вам об этом, указав ошибку.

Не всегда очевидно, что первое чтение проверяется, является ли метод переопределением. Например, правильная ковариантность возвращаемого типа:

class A {};
class B : public A {};

class Base {
public:
    virtual A* foo() {
        return nullptr;
    }
};

class Derived : public Base {
public:
    B* foo() override {
        return nullptr;
    }
};

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

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

class App {
public:
    App() {}
    virtual ~App() {}  // <---
    void run() {
        this->speak();
    }
    virtual void speak() {
        std::cout << "Base\n";
    };
};
1
ответ дан RudolfW 16 August 2018 в 14:28
поделиться
  • 1
    Кроме того, технически переопределение - это не ключевое слово, а контекстный идентификатор, но это не относится к делу. – RudolfW 4 December 2014 в 20:57