Здравствуйте, T4r4sB, Вы писали:
TB>Не понял, каждая ячейка отдельный класс что ли?
Нет, конечно.
TB>Или наследование абстрактных классов требует дополнительный указатель в каждом экземпляре?
Да, как частный случай.
В общем случае не только абстрактных, а имеющих хотя бы одну виртуальную функцию.
Здравствуйте, Patalog, Вы писали:
P>Не очень понял как такое получилось В объекте же афаир только vptr, а сама таблица относится в классу, а не к инстансу?
Таблица относится к каждому классу с виртуальными функциями.
В примере Impl содержит vptr для классов Inter1 и Inter2:
Здравствуйте, T4r4sB, Вы писали: TB>Какая-то говняная реализация ООП, это что за говноязык? А, это же С++, в котором не платят за то, чем не пользуются.
Это еще цветочки.
Настоящая веселуха начинается когда объект содержит в себе несколько подобъектов одного класса.
Или с виртуальным наследованием, ромбы всякие.
С другой стороны, не нравится — не используешь.
Вот я практически не пользуюсь множественным наследованием от не чисто абстрактных классов, а также виртуальным наследованием.
Ромб только в один раз делал, но там задача была 1 в 1 как iostream — in/out сериализация.
хъ
P>>Не очень понял как такое получилось В объекте же афаир только vptr, а сама таблица относится в классу, а не к инстансу? Q>Таблица относится к каждому классу с виртуальными функциями.
Q>В примере Impl содержит vptr для классов Inter1 и Inter2:
С vptr все понятно, в исходном сообщении было про vtbl, об чем я и удивился.
Здравствуйте, Marty, Вы писали:
M>А что это и как работает?
Типа если функция принимает указатель на интерфейс, то на самом деле она принимает пару указателей: указатель на объект, и указатель на vtbl, в которой этот объект реализует этот интерфейс.
Как раз чтоб в объекте не хванить все эти указатели на vtbl.
Здравствуйте, T4r4sB, Вы писали:
M>>А что это и как работает?
TB>Типа если функция принимает указатель на интерфейс, то на самом деле она принимает пару указателей: указатель на объект, и указатель на vtbl, в которой этот объект реализует этот интерфейс. TB>Как раз чтоб в объекте не хванить все эти указатели на vtbl.
Ну, таки где-то эти указатели всё равно хранить надо. И что мешает присунуть не тот указатель на vtbl?
Здравствуйте, Marty, Вы писали:
M>Ну, таки где-то эти указатели всё равно хранить надо.
Да, один лишний указатель приходится гонять по стеку. Это лучше, чем в каждом экземпляре хранить 100500 указателей.
Ещё если ты в структуре хранишь Box<dyn MyInderface> (unique_ptr<MyInterface>), то он жрёт вдвое больше.
M>И что мешает присунуть не тот указатель на vtbl?
Если это работает на уровне языка — то у тебя при вот таком:
fn foo(arg: &dyn MyInterface) { // якобы принимает указатель на интерфейс/абстрактный класс с названием MyInterface
...
}
...
let object: MyClass;
foo(&object)
Если попытаешься сэмулировать подобное в С++, то я хз, наверное можно как-то извернуться на имплисит конструкторах и шаблонах, чтоб работало более-менее удобно.
Здравствуйте, T4r4sB, Вы писали:
M>>Ну, таки где-то эти указатели всё равно хранить надо.
TB>Да, один лишний указатель приходится гонять по стеку. Это лучше, чем в каждом экземпляре хранить 100500 указателей. TB>Ещё если ты в структуре хранишь Box<dyn MyInderface> (unique_ptr<MyInterface>), то он жрёт вдвое больше.
А если объект реализует много интерфейсов? Где эти указатели хранятся
Так-то в C++, если объект реализует один интерфейс, то и указатель на vtbl будет один, и никаких проблем
Здравствуйте, T4r4sB, Вы писали:
M>>А если объект реализует много интерфейсов? Где эти указатели хранятся
TB>Посмотри ещё раз на мой пример — зачем что-то хранить в объекте?
Здравствуйте, Marty, Вы писали:
M>Ну, не в объекте, а вместе с ним. Какая разница?
Разница в том, что объект не жиреет от переизбытка интерфейсов.
Указатель на интерфейс собирается в пару с указателем на объект только тогда, когда интерфейс реально становится нужен.
Здравствуйте, T4r4sB, Вы писали:
M>>Ну, не в объекте, а вместе с ним. Какая разница?
TB>Разница в том, что объект не жиреет от переизбытка интерфейсов. TB>Указатель на интерфейс собирается в пару с указателем на объект только тогда, когда интерфейс реально становится нужен.
А, ну попонятнее стало. Типа есть какая-то отдельная таблица указателей на VTBL тех интерфейсов, которые поддерживает объект? Да, по идее, должно места сэкономить. А как dynamic_cast работает? Можно из одного интерфейса получить другой или ошибку, если не поддерживается? Ну и лишняя косвенность вроде как получается, хотя и не при каждом вызове виртуального метода, а только при передаче объекта.
В принципе, в плюсах подобное тоже можно сделать, будет не слишком удобно, но оно точно вот так постоянно надо? Не так часто объекты реализуют множество различных интерфейсов, и не так часто эти объекты настолько малы и их так много, чтобы это играло какую-то заметную роль
Здравствуйте, Marty, Вы писали:
M>>>А если объект реализует много интерфейсов? Где эти указатели хранятся TB>>Посмотри ещё раз на мой пример — зачем что-то хранить в объекте? M>Ну, не в объекте, а вместе с ним. Какая разница?