Интерфейсы(с виртуальными и невиртуальными методами)
1. Интерфейсы в целом.
1.1. Для объявления интерфейса используется контекстное слово “interface” вместе с ключевым словом “class”
class interface MyInterface{
// ***
};
1.2. Объявления реализации интерфейса осуществляется так же как и при наследовании класса от другого класса, только без указания модификатора доступа наследования.
class interface MyInterface: OtherInterface1, OtherInterface2{
// ***
};
1.3. При реализации интерфейса запрещается множественное наследование от классов(целесообразность этого пункта под вопросом)
1.4. Интерфейс может использоваться так же как и концепт (под капотом компилятор создаёт концепт без имени с проверкой std::is_base_of):
template<MyInterface T>
void func(T x);
1.5. Уточнения std::is_base_of для интерфейсов, и/или добавление отдельного библиотечного класса для такой проверки.
1.6. Методы с реализацией по умолчанию:
class interface MyInterface{
// Метод без реализации
void test();
// Метод с реализацией по умолчанию вне тела класа или с реализацией компилятора(к
// примеру операторы сравнения начиная с c++20
void test2() = default;
// Метод с реализацией по умолчанию внутри класа
void test3() = default {
// ...
}
};
1.7. Для всех модификаторов доступа разрешены пользовательские типы и статические члены.
1.8. Для модификатора доступа “protected” разрешены также методы с реализацией по умолчанию.
1.9. Для модификатора доступа “public” разрешены также методы с и без реализации.
1.10. Для модификатора доступа “private” разрешено все то же что и в обычном классе, а также приватный конструктор по умолчанию, который всегда вызывается только конструкторами реализующих классов или в интерфейсах, которые расширяют интерфейс.
1.11. Члены с модификатором “private” используются методами с реализацией по умолчанию.
1.12. Для переопределения метода при колизии используется ключевое слово “using”:
class interface MyInterfaceA{
int test(int a, int b) = default{
return a + b;
}
};
class interface MyInterfaceB {
int test(int a, int b) = default{
return a + b;
}
};
class interface MyInterfaceC: MyInterfaceA, MyInterfaceB {
using int MyInterfaceB::test(int a, int b);
};
class MyClass: MyInterfaceA, MyInterfaceB {
using int MyInterfaceA::test(int a, int b);
};
1.13. Модификатор доступа по умолчанию - “public” .
1.14. Определения виртуального или невиртульного метода:
class interface MyInterfaceA{
void test1();
virtual void test2();
};
class interface MyInterfaceB: MyInterfaceA{
void test1() = default{
// ...
}
virtual void test2();
};
class MyClassB: MyInterfaceB{
};
class interface MyInterfaceC: MyInterfaceB{
virtual void test2() = default{
// ...
}
};
class MyClassC: MyInterfaceC{
};
int main(){
MyInterfaceA * ptr; // ОШИБКА: у интерфейса есть нереализованые невиртуальные методы
MyInterfaceB * ptr; // ОК
MyClassB obj; // ОШИБКА: у интерфейса есть нереализованые виртуальные методы
MyClassC obj; // ОК
}
2. Невиртуальные методы интерфейса
2.1. Разрешается использования “override”, “final”, “= 0” для невиртуальных методов интерфейса для проверки в классе реализации метода:
2.2. Специальная конструкция для определения типа класса, который реализуюет невиртуальный метод (определяется при каждой реализации, так как невиртуальный метод недоступен по ссылке или указателю интерфейса или класса, который не реализует метод); (используется как синтаксический сахар над CRTP, и в случае переопределения метода):