У меня есть следующий - упрощенный - код C ++ 11, используемый для отвлечения чтения из хранилища объектов или из файловой системы:
ObjectLikeReader::open
- это виртуальная функция, возвращающая * Реализация 1005 *. Handle::read
читает что-то из базового объекта.
class Handle {
public:
virtual std::string read() = 0;
virtual ~Handle() = default;
};
class ObjectLikeReader {
public:
virtual std::unique_ptr<Handle> open() = 0;
virtual ~ObjectLikeReader() = default;
};
// Specialization
class FileReader : public ObjectLikeReader {
public:
std::unique_ptr<Handle> open() override;
private:
class InternalHandle;
};
class FileReader::InternalHandle : public Handle {
public:
InternalHandle(){};
std::string read() override {
return "hello";
}
};
std::unique_ptr<Handle> FileReader::open() {
return std::unique_ptr<Handle>(new InternalHandle());
}
std::string read(ObjectLikeReader* reader) {
return reader->open()->read();
}
int main() {
FileReader r;
std::cout << read(&r) << std::endl;
}
Вся диспетчеризация выполняется с использованием виртуальных функций и работает отлично. Помимо производительности в узком l oop, которая командует, обращая внимание на полиморфизм stati c:
#include <iostream>
#include <string>
template <class T>
class Handle {
public:
std::string read() {
return static_cast<T*>(this)->read();
}
protected:
~Handle() = default;
};
template <class T, class H>
class ObjectLikeReader {
public:
Handle<H> open() {
return static_cast<T*>(this)->open();
}
protected:
~ObjectLikeReader() = default;
};
// Specialization
class FileReaderHandle : Handle<FileReaderHandle> {
public:
FileReaderHandle(){};
std::string read() {
return "hello";
}
};
class FileReader : public ObjectLikeReader<FileReader, FileReaderHandle> {
public:
FileReaderHandle open() {
return FileReaderHandle();
}
};
int main() {
FileReader r;
std::cout << r.open().read() << std::endl;
}
Я не совсем удовлетворен этой реализацией. Есть ли способ достичь той же функциональности, что и во втором примере?:
- Не требуя двойной шаблонный параметр (черты, может быть, не уверен ...),
- В идеале, не имея сделать дескриптор класса publi c.
Спасибо!
Редактировать: Исправлено глупое определение отсутствующего конструктора, приводящее к ошибке компиляции.