8

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

struct A { 
    void foo(); 
}; 

int main() { 
    A a;  // <-- Works in both VC2013 and g++ 
    a.foo(); // <-- Error in both VC2013 and g++ 
} 

Вот такая же ситуация, но один, который включает в себя наследование. Подкласс Bar расширяет базовый класс Foo. Foo определяет способ g(). Bar объявляет одноименном метод, но не определяет его:

#include <iostream> 

struct Foo { 
    void g() { std::cout << "g\n"; } 
}; 

struct Bar : Foo { 
    void g(); 
}; 

int main() { 
    Bar b;  // Works in both VC2013 and g++ 
    b.Foo::g(); // Works in both VC2013 and g++ 
    b.g();  // Error in both VC2013 and g++ 
} 

Вот вариант выше. Единственное отличие в том, что g() является virtual как к Foo и Bar:

#include <iostream> 

struct Foo { 
    virtual void g() { std::cout << "g\n"; } 
}; 

struct Bar : Foo { 
    virtual void g(); 
}; 

int main() { 
    Bar b;  // Works in g++. But not in VC2013, which gives 
       // 'fatal error LNK1120: 1 unresolved externals' 

    b.Foo::g(); // Works in g++, but VC2013 already failed on b's construction 
    b.g();  // Error in g++, but VC2013 already failed on b's construction 
} 

Смотрите комментарии кода для контраста различного поведения между VC2013 и г ++.

  1. Какой компилятор прав, если таковые имеются?
  2. Почему у компилятора VC2013 есть несколько разных жалоб в своей версии с ключевым словом virtual по сравнению с тем, что в его версии, без ключевого слова virtual?
  3. Неиспользованные неиспользуемые методы всегда разрешены? Если нет, то каковы все случаи, когда они не разрешены?
  4. Заявление Barg() считается переопределяющим , даже если Bar не содержит определения?
+0

vtable ссылается на конструктор, и ему нужны адреса виртуальных функций, поэтому ошибка VC2013 представляется разумной. – BartoszKP

ответ

8

Какой у вас компилятор?

Они оба справа. Ваш код неправильный, не требуется диагностика. [Class.virtual]/11

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

[intro.compliance]/2:

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

Ознакомьтесь с настройками оптимизации для GCC, они могут влиять на поведение.


неиспользованные неопределенные методы всегда разрешено?

Функция-член должна быть определена тогда и только тогда, когда она используется odr. [Basic.def.УСО]/3:

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

Теперь рассмотрит [basic.def.odr]/2:

Выражение является потенциально оценивало, если он не является невычисленным операндом (пункт 5) или Подвыражение их.
[...]
Виртуальная функция-член используется odr, если она не является чистой.
Неперегруженная функция, имя которой отображается как потенциально оцениваемое выражение или член набора функций-кандидатов, если оно выбрано с помощью разрешения перегрузки при упоминании потенциально оцениваемого выражения, используется как odr, если оно не является чистая виртуальная функция, и ее имя явно не квалифицировано.

Вы по-прежнему разрешено использовать неопределенные функции невиртуальные члена внутри decltype или sizeof. Но нечистые виртуальные функции используются как простые, просто потому, что они не чисты.


декларация Имеет ли Бара д() считаются перекрывая даже если Bar не дает определение?

Да.

+0

Относительно «Они оба правы», вы имеете в виду, что для g ++ вполне нормально строить 'b' (чей класс имеет виртуальный метод), в то время как VC2013 не может, потому что это неуказанное поведение? – CodeBricks

+1

@CodeBricks Это почти идентично неопределенному поведению. Проверьте [этот ответ] (http://stackoverflow.com/questions/22180312/difference-between-undefined-behavior-and-ill-formed-no-diagnostic-message-requ). – Columbo

+0

Означает ли это, что нечистая виртуальная функция не должна вызываться как odr? – CodeBricks

Смежные вопросы