I have an idea how to design an object in a better way. I would like
to give you
my thought example. Please let me know what you think if it is best
object design.
Please recommend me any book which it teaches me how to design C++ OOP
better as long
as I know how to program OOP in C++.
Think of ancient 6502 microprocessor which it was used for Commodore,
Atari, and
Apple II. This MPU_6502 is an object of MPU_6502 class. All member
variables are
hidden like internal registers of A, X, and Y. Only address bus and
data bus
member variables are available using Set() and Get() functions.
This MPU_6502 object can be reused to the client users. What happen
if
programmers want to create another object which it is called
MPU_6502_Debug. This
MPU_6502 object guards against MPU_6502_Debug from accessing internal
registers
using Set() and Get() functions. MPU_6502_Debug object needs to find
a way how to
obtain internal registers from MPU_6502 object.
The friend keyword may be the option so friend class MPU_6502_Debug
can be added
into MPU_6502 class and you create a pointer in MPU_6502_Debug object
to access
MPU_6502 object's internal registers.
If you think that friend keyword is a bad OOP design, please offer me
another
good example how MPU_6502 object and MPU_6502_Debug object can be done
to process
internal registers inside main() function.
Please advise. I appreciate your help. Take a look at my C++ OOP
code below. They are too short codes as examples.
class MPU_6502
{
public:
MPU_6502() {}
~MPU_6502() {}
void Run() { /* Process Address Bus and Data Bus to modify internal
A, X, and Y registers */ }
unsigned int Get_Address_Bus() { return Address_Bus; }
unsigned int Get_Data_Bus() { return Data_Bus; }
void Set_Data_Bus(unsigned int data_bus) { Data_Bus = data_bus; }
// You are not allowed to use Set() & Get() functions below as a true
black box.
// void Set_A(unsigned int a) { A = a; }
// void Set_X(unsigned int x) { X = x; }
// void Set_Y(unsigned int y) { Y = y; }
// unsigned int Get_A() const { return A; }
// unsigned int Get_X() const { return X; }
// unsigned int Get_Y() const { return Y; }
private:
unsigned int A;
unsigned int X;
unsigned int Y;
unsigned int Address_Bus;
unsigned int Data_Bus;
};
class MPU_6502_Debug
{
public:
MPU_6502_Debug() {}
~MPU_6502_Debug() {}
void Run()
{ /* Need to get internal registers from MPU_6502 object to process
debugging */ }
void Set_A(unsigned int a) { A = a; }
void Set_X(unsigned int x) { X = x; }
void Set_Y(unsigned int y) { Y = y; }
private:
unsigned int A;
unsigned int X;
unsigned int Y;
};
int main(void)
{
unsigned char* RAM = new unsigned char [0x10000];
MPU_6502 mpu;
mpu.Run(); // Run many times every time address bus comes.
mpu.Set_Data_Bus( RAM[ mpu.Get_Address_Bus() ] ); // Get Data bus
from RAM's address bus
mpu.Run(); // Continues running as long as it can.
/* This MPU_6502 object is a black box like a chip. This chip has
only address bus and
data bus. You send message to MPU_6502 object to retreive address
bus and data
bus. It does not allow you to access internal registers, but only
Run() can do process
internal registers. No Get internal registers functions and set
internal registers
functions are allowed to be used to the client. This MPU_6502 object
is a good
object design for best data protection. */
MPU_6502_Debug mpu_debug; // You can define MPU_6502_Debug object
anytime you want.
for (int loop = 0; loop < 10; loop++) // can be endless loop as you
want.
{
mpu.Run();
mpu_debug.Set_A( 0x40 ); // How can you do it?
mpu_debug.Set_X( 0xC1 ); // How can you do it?
mpu_debug.Set_Y( 0x80 ); // How can you do it?
mpu_debug.Run();
}
delete [] RAM;
return 0;
}
Nephi