Виртуальный метод не «удалить» в состоянии в C ++ 0x? - PullRequest
4 голосов
/ 24 июня 2011

Сообщение об ошибке кажется немного ошибочным в сценарии, когда мы пытаемся delete метод virtual.

prog.cpp:4:16: error: deleted function 'virtual void Test::foo()'
prog.cpp:8:2: error: used here

код

struct Test : public Base
{
  Test() {}
  virtual void foo () = delete;  // error
};

Способ virtual не delete способен по той же причине, почему они не могут остаться нереализованными в C ++ 03? Есть ли способ упомянуть, что Test намеренно не реализует virtual foo()?

Ответы [ 5 ]

9 голосов
/ 24 июня 2011

Термин use имеет конкретное определение в стандарте, и, в частности, для виртуальных функций определение odr-used :

§3.2 / 2 (C ++ 0x FDIS) [...] Виртуальная функция-член используется odr, если она не является чистой. [...]

Где odr-used - это новый термин в готовящемся стандарте, который относится к тому, что предыдущий стандарт назывался просто :

§3.2 / 2 (текущий стандарт) [...]Виртуальная функция-член используется, если она не является чистой. [...]

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

3 голосов
/ 24 июня 2011

Должны быть реализованы все не чистые виртуальные функции, независимо от того, используете вы их или нет :

struct Test
{
  Test() {}
  virtual void foo();
};

int main() {
   Test* t = new Test;
   // ^ it seems to have to be dynamic allocation to coerce the error out
}

/* Output:
/home/Y3oGMf/ccOLuYWf.o: In function `main':
prog.cpp:(.text+0x17): undefined reference to `vtable for Test'
collect2: ld returned 1 exit status
*/

Я думаю, вы видите немного странное сообщение об ошибке относительно используйте удаленной функции по аналогичной причине.Это просто из-за того, как все работает внутри.Более разумное сообщение об ошибке может быть в строке, где вы пытались delete virtual член функции, говоря: «это не сработает. Это вызовет проблемы, потому что эта реализация должна существовать."

В любом случае delete функция интерфейса не имеет смысла.Наследование добавляет функциональность;это не убирает это.Обратите внимание, как создание функции-члена pure virtual запрещает создание экземпляров всего класса: производные классы должны повторно реализовать функциональность, чтобы она не терялась.

2 голосов
/ 24 июня 2011

Насколько я понимаю, ключевое слово delete предназначено для удаления реализации по умолчанию, созданной компилятором.Для виртуальных методов не существует реализации по умолчанию, сгенерированной компилятором.

1 голос
/ 27 сентября 2014

Удаленные виртуальные функции разрешены, но их перегрузка запрещена.

§10.3 (11) говорит:

Виртуальная функция , объявленная в классе должно быть определено или объявлено чистым (10.4) в этом классе или в обоих;но никакой диагностики не требуется (3.2).

§8.4.1 говорит, что определена удаленная функция .

И §10.3 (16) говорит:

Функция с удаленным определением (8.4) не должна переопределять функцию, которая не имеет удаленного определения.Аналогично, функция, которая не имеет удаленного определения, не должна переопределять функцию с удаленным определением.

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

Итак, следующий код некорректно сформирован:

struct Base {
    virtual void foo();
};
struct Derived : public Base {
    virtual void foo() = delete;
};

Но следующий код правильно сформирован:

struct Base {
    virtual void foo() = delete;
};
struct Derived : public Base {
    virtual void foo() = delete;
};

DEMO

У OP была либо ошибка компилятора, либо проблема QoI (трудно сказать, потому что он не опубликовал весь код), которая с тех пор была исправлена.

0 голосов
/ 24 июня 2011

Возможно, вам не следует наследовать от класса, который ТРЕБУЕТ чего-либо, если ваш производный класс не может его реализовать. Вероятно, вам не нужно извлекать уроки из этого класса.

Это все равно, что сказать: «Я строю лучшую машину. Это что-то вроде машины, но не использует колеса». Вы уверены, что это машина тогда на первом месте?

Или вы спрашиваете это просто из любопытства?

...