Интерфейсы(с виртуальными и невиртуальными методами)

Виталий Псевдокенко
Виталий Псевдокенко

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; // ОК

}

 

-5
рейтинг
1 комментарий
Виталий Псевдокенко

2. Невиртуальные методы интерфейса

2.1. Разрешается использования “override”, “final”, “= 0”   для невиртуальных методов интерфейса для проверки в классе реализации метода:

class interface MyInterface{
    void test1();

    void test_final();};
class MyClass1{public:
    void test1() override { //...} // ОК
    void test2() override { //...} // ОШИБКА

    void test_final() final override { // ...}}
class MyClass2: public MyClass1{public:
    void test_final() override { // ...} // ОШИБКА
    void test_final() { // ...}          // ОК}
}

2.2. Специальная конструкция для определения типа класса, который реализуюет невиртуальный метод (определяется при каждой реализации, так как невиртуальный метод недоступен по ссылке или указателю интерфейса или класса, который не реализует метод); (используется как синтаксический сахар над CRTP, и в случае переопределения метода):

class interface MyInterface{

    auto test(); // auto - может содержать тип класса, который реализует интерфейс
}

class MyClass1: MyInterface{

     MyClass1 test() override{//...} //ОК

     int test() override{//...} //ОШИБКА 
}

class MyClass2: public MyClass1{

     MyClass2 test() override{//...} //ОК

}​

 

Виталий Псевдокенко
Другие идеи
Группа создана, чтобы собирать предложения к стандарту C++, организовывать их внутренние обсуждения, помогать готовить их для отправки в комитет и защищать на общих собраниях в рабочей группе по С++ Международной организации по стандартизации (ISO).
Все предложения