Сообщение Re[9]: как сократить количество vtbl от 25.04.2017 17:18
Изменено 25.04.2017 19:07 Erop
Re[9]: как сократить количество vtbl
Здравствуйте, qaz77, Вы писали:
Q>Здравствуйте, Erop, Вы писали:
Q>>>Если все перевести на NVI, то нельзя будет Bar'ы скармливать функциям, ожидающим полиморфное поведение.
Q>>>Либо все такие функции переделывать в шаблоны.
E>>Почему?
E>>С точки зрения клиентского кода вообще ничего, кроме того, что кастить надо иначе, не поменяется же?
Q>Функции ожидают параметр ISerializable& (к примеру) и зовут его виртуальные функции,
Q>т.е. полиморфизм времени выполнения в чистом виде.
Q>Если я для какого-то IBar: public ISerializable уберу наследование ISerializable
Q>и сделаю не виртуальные функции load, save и пр. одноименные членам ISerializable,
Q>то IBar нельзя будет скормить функциям, ожидающим ISerializable.
Почему?
Теперь тот, кто выводился из IClonable, может продолжать это делать, только лучше бы при этом ещё определить operator IClonable*
Но в целом для него ничего не поменяется, и для того, кто использует интерфейс IClonable не поменяется, за исключением того, что
нельзя запрашивать поддерживаемые интерфейсы через dynamic_cast.
Единственное что поменяется, так это если кто-то поддерживает несколько интерфейсов из ISuperBar, то он может вывестись просто публично из ISuperBar и реализовать нужные методы и операторы приведения
Q>Сделать полиморфное поведение (времени компиляции) по одноименным функциям-членам можно
Q>в шаблонной функции, когда не важно виртуальные функции-члены или нет.
Это место не понял о чём тут речь, но, IMHO, это не важно.
Q>Вот я и имел в виду, что если один из многих классов переделать на NVI,
Q>то тогда все функции, куда его передавали как абстрактный интерфейс, нужно из обычных функций переделывать в шаблонные:
Не нужно
Как видишь ничего шаблонным делать не надо.
Q>полиморфизм времени выполнения использовать не получится, т.к. общей базы не будет.
Почему? ISuperBar жеж?
ISerializable это такое view на ISuperBar, в котором в public видны только методы ISerializable и всё.
То есть для программиста он останется таким же ISerializable, за исключением того, что QueryInterface иначе далать надо, а для С++ это будет просто NVI view на интерфейс, но это будет спрятано за protected
Q>Здравствуйте, Erop, Вы писали:
Q>>>Если все перевести на NVI, то нельзя будет Bar'ы скармливать функциям, ожидающим полиморфное поведение.
Q>>>Либо все такие функции переделывать в шаблоны.
E>>Почему?
E>>С точки зрения клиентского кода вообще ничего, кроме того, что кастить надо иначе, не поменяется же?
Q>Функции ожидают параметр ISerializable& (к примеру) и зовут его виртуальные функции,
Q>т.е. полиморфизм времени выполнения в чистом виде.
Q>Если я для какого-то IBar: public ISerializable уберу наследование ISerializable
Q>и сделаю не виртуальные функции load, save и пр. одноименные членам ISerializable,
Q>то IBar нельзя будет скормить функциям, ожидающим ISerializable.
Почему?
// SuperBar.h
struct ISerializable;
struct IClonable;
struct IDeletable
// И т. д...
class ISuperBar {
public:
virtual operator ISerializable*() { return 0; }
virtual operator IClonable*() { return 0; }
virtual operator IDeletable*() { return to<IDeletable>(); }
// И т. д...
protected:
template<typename I> I* to() { return (I*)this; }
template<typename const I> I* to() const { return (const I*)this; }
virtual ~ISuperBar() {}
// ISerializable
virtual void Serialize() { assert( false ); }
// IClonable
virtual ISuperBar* Clone() { assert( false ); }
// IDeletable
virtual void Delete() { delete this; }
// И т. д...
};
struct IDeletable : ISuperBar {
using ISuperBar::Delete;
};
////////////////////////////
// Serializable.h
#include <SuperBar.h>
struct ISerializable : ISuperBar {
using ISuperBar::Serialize;
};
////////////////////////////
// Clonable.h
#include <SuperBar.h>
struct IClonable : ISuperBar {
using ISuperBar::Clone;
};
Теперь тот, кто выводился из IClonable, может продолжать это делать, только лучше бы при этом ещё определить operator IClonable*
Но в целом для него ничего не поменяется, и для того, кто использует интерфейс IClonable не поменяется, за исключением того, что
нельзя запрашивать поддерживаемые интерфейсы через dynamic_cast.
Единственное что поменяется, так это если кто-то поддерживает несколько интерфейсов из ISuperBar, то он может вывестись просто публично из ISuperBar и реализовать нужные методы и операторы приведения
Q>Сделать полиморфное поведение (времени компиляции) по одноименным функциям-членам можно
Q>в шаблонной функции, когда не важно виртуальные функции-члены или нет.
Это место не понял о чём тут речь, но, IMHO, это не важно.
Q>Вот я и имел в виду, что если один из многих классов переделать на NVI,
Q>то тогда все функции, куда его передавали как абстрактный интерфейс, нужно из обычных функций переделывать в шаблонные:
Не нужно
struct CBar : ISuperBar {
// ISerializable
operator ISerializable*() { return to<ISerializable>(); }
void Serialize() { /*реализация*/ }
// IClonable
operator IClonable*() { return to<IClonable>(); }
IClonable* Clone() { /*реализация*/ }
};
class CFoo : public IClonable {
public:
CFoo* Clone() { return new CFoo( *this ); }
};
void foo( IClonable* p ) { p->Clone()->operator IDeletable*()->Delete(); }
CBar b;
foo( b );
CFoo f;
foo( &f );
Как видишь ничего шаблонным делать не надо.
Q>полиморфизм времени выполнения использовать не получится, т.к. общей базы не будет.
Почему? ISuperBar жеж?
ISerializable это такое view на ISuperBar, в котором в public видны только методы ISerializable и всё.
То есть для программиста он останется таким же ISerializable, за исключением того, что QueryInterface иначе далать надо, а для С++ это будет просто NVI view на интерфейс, но это будет спрятано за protected
Re[9]: как сократить количество vtbl
Здравствуйте, qaz77, Вы писали:
Q>Если я для какого-то IBar: public ISerializable уберу наследование ISerializable
Q>и сделаю не виртуальные функции load, save и пр. одноименные членам ISerializable,
Q>то IBar нельзя будет скормить функциям, ожидающим ISerializable.
Почему?
Теперь тот, кто выводился из IClonable, может продолжать это делать, только лучше бы при этом ещё определить operator IClonable*
Но в целом для него ничего не поменяется, и для того, кто использует интерфейс IClonable не поменяется, за исключением того, что
нельзя запрашивать поддерживаемые интерфейсы через dynamic_cast.
Единственное что поменяется, так это если кто-то поддерживает несколько интерфейсов из ISuperBar, то он может вывестись просто публично из ISuperBar и реализовать нужные методы и операторы приведения
Q>Сделать полиморфное поведение (времени компиляции) по одноименным функциям-членам можно
Q>в шаблонной функции, когда не важно виртуальные функции-члены или нет.
Это место не понял о чём тут речь, но, IMHO, это не важно.
Q>Вот я и имел в виду, что если один из многих классов переделать на NVI,
Q>то тогда все функции, куда его передавали как абстрактный интерфейс, нужно из обычных функций переделывать в шаблонные:
Не нужно
Как видишь ничего шаблонным делать не надо.
Q>полиморфизм времени выполнения использовать не получится, т.к. общей базы не будет.
Почему? ISuperBar жеж?
ISerializable это такое view на ISuperBar, в котором в public видны только методы ISerializable и всё.
То есть для программиста он останется таким же ISerializable, за исключением того, что QueryInterface иначе далать надо, а для С++ это будет просто NVI view на интерфейс, но это будет спрятано за protected
Q>Если я для какого-то IBar: public ISerializable уберу наследование ISerializable
Q>и сделаю не виртуальные функции load, save и пр. одноименные членам ISerializable,
Q>то IBar нельзя будет скормить функциям, ожидающим ISerializable.
Почему?
// SuperBar.h
struct ISerializable;
struct IClonable;
struct IDeletable
// И т. д...
class ISuperBar {
public:
virtual operator ISerializable*() { return 0; }
virtual operator IClonable*() { return 0; }
virtual operator IDeletable*() { return to<IDeletable>(); }
// И т. д...
protected:
template<typename I> I* to() { return (I*)this; }
template<typename const I> I* to() const { return (const I*)this; }
virtual ~ISuperBar() {}
// ISerializable
virtual void Serialize() { assert( false ); }
// IClonable
virtual ISuperBar* Clone() { assert( false ); }
// IDeletable
virtual void Delete() { delete this; }
// И т. д...
};
struct IDeletable : ISuperBar {
using ISuperBar::Delete;
};
////////////////////////////
// Serializable.h
#include <SuperBar.h>
struct ISerializable : ISuperBar {
using ISuperBar::Serialize;
};
////////////////////////////
// Clonable.h
#include <SuperBar.h>
struct IClonable : ISuperBar {
using ISuperBar::Clone;
};
Теперь тот, кто выводился из IClonable, может продолжать это делать, только лучше бы при этом ещё определить operator IClonable*
Но в целом для него ничего не поменяется, и для того, кто использует интерфейс IClonable не поменяется, за исключением того, что
нельзя запрашивать поддерживаемые интерфейсы через dynamic_cast.
Единственное что поменяется, так это если кто-то поддерживает несколько интерфейсов из ISuperBar, то он может вывестись просто публично из ISuperBar и реализовать нужные методы и операторы приведения
Q>Сделать полиморфное поведение (времени компиляции) по одноименным функциям-членам можно
Q>в шаблонной функции, когда не важно виртуальные функции-члены или нет.
Это место не понял о чём тут речь, но, IMHO, это не важно.
Q>Вот я и имел в виду, что если один из многих классов переделать на NVI,
Q>то тогда все функции, куда его передавали как абстрактный интерфейс, нужно из обычных функций переделывать в шаблонные:
Не нужно
struct CBar : ISuperBar {
// ISerializable
operator ISerializable*() { return to<ISerializable>(); }
void Serialize() { /*реализация*/ }
// IClonable
operator IClonable*() { return to<IClonable>(); }
IClonable* Clone() { /*реализация*/ }
};
class CFoo : public IClonable {
public:
CFoo* Clone() { return new CFoo( *this ); }
};
void foo( IClonable* p ) { p->Clone()->operator IDeletable*()->Delete(); }
CBar b;
foo( b );
CFoo f;
foo( &f );
Как видишь ничего шаблонным делать не надо.
Q>полиморфизм времени выполнения использовать не получится, т.к. общей базы не будет.
Почему? ISuperBar жеж?
ISerializable это такое view на ISuperBar, в котором в public видны только методы ISerializable и всё.
То есть для программиста он останется таким же ISerializable, за исключением того, что QueryInterface иначе далать надо, а для С++ это будет просто NVI view на интерфейс, но это будет спрятано за protected