Я нахожусь в процессе разработки виртуального процессора и хочу представить регистры разных размеров, которые будет использовать виртуальный процессор.Я также хотел бы поместить их в один контейнер независимо от их фактических размеров и / или типов.
У меня была бы структура, которая выглядит так, чтобы хранить регистры
struct Memory {
std::vector<std::shared_ptr<Register>> bank;
};
I 'Я пытаюсь создать базовый пустой класс как таковой:
struct Register {};
Теперь я буду наследовать от этого базового класса для создания различных типов поддерживаемых регистров.Эти регистры также зависят от нескольких typedefs ...
typedef std::int8_t i8;
typedef std::int16_t i16;
typedef std::int32_t i32;
typedef std::int64_t i64;
typedef std::uint8_t u8;
typedef std::uint16_t u16;
typedef std::uint32_t u32;
typedef std::uint64_t u64;
const u16 BYTE = 0x08, WORD = 0x10, DWORD = 0x20, QWORD = 0x40;
Допустим, я хочу иметь регистр, в котором его базовый тип данных - u8, другой - u16 и так далее ...
struct Register8 : Register {
u8 value;
u8 getValue() const { return value; }
};
struct Register16 : Register {
u16 value;
u8 getValue() const { return value; }
};
struct Register32 : Register {
u32 value;
u32 getValue() const { return value; }
};
struct Register64 : Register {
u64 value;
u64 getValue() const { return value; }
};
Так что это достаточно просто, однако мне не нравится тот факт, что я называю каждый из моих классов регистров по-разному, и я вижу некоторый дублирующий код, отличный от различий в типах, поэтому мы должны иметь возможность создаватьшаблон ...
struct Register{};
template<typename T>
Register_t : Register {
T value;
T getValue() const { return value; }
};
Это достаточно просто;Однако я хотел бы специализировать этот класс:
struct Register {};
template<typename T>
struct Register_t : Register {
T value;
T getValue() const { return value; }
};
template<>
struct Register_t<u8> {
u8 value;
u8 getValue() const { return value; }
};
template<>
struct Register_t<u16> {
u16 value;
u16 getValue() const { return value; }
};
template<>
struct Register_t<u32> {
u16 value;
u16 getValue() const { return value; }
};
template<>
struct Register_t<u64> {
u16 value;
u16 getValue() const { return value; }
};
Хорошо, это восходит к тому, что я говорил ранее о дублирующемся коде, и мы вводим больше, однако в моей ситуации это будут единственные приемлемые типы, когда-либо, поэтомубит дублирования не проблема.
Пока что все так хорошо ...
Теперь, скажем, я пытаюсь использовать это ...
main.cpp
#include <iostream>
#include "Register.h"
int main () {
Register_t<u8> r8;
r8.value = 8;
Register_t<u16> r16;
r16.value = 16;
Register_t<u32> r32;
r32.value = 32;
Register_t<u64> r64;
r64.value = 64;
Memory mem;
mem.bank.push_back( std::make_shared<Register>( r8 ) );
mem.bank.push_back( std::make_shared<Register>( r16 ) );
mem.bank.push_back( std::make_shared<Register>( r32 ) );
mem.bank.push_back( std::make_shared<Register>( r64 ) );
return EXIT_SUCCESS;
};
Хорошо, я успешно сохранил их как общие указатели в векторе.Теперь возникает проблема или проблема ... Давайте попробуем получить доступ к этим значениям из класса
int main () {
// ....
for ( auto& b : mem.bank ) {
std::cout << b->getValue() << '\n'; // Uh oh class Register has no member getValue() ...
}
return EXIT_SUCCESS;
}
Итак, вот моя проблема;Я не уверен, как косвенно вызвать функцию getValue()
унаследованного класса или как правильно наследовать этот тип структуры проектирования - иерархию классов.Или, если я полностью исключу специализацию ... Это то, где я застрял, и любая помощь будет благодарна.