Salve ragazzi, ho una perplessità sull'utilizzo dei puntatori:

Ultimamente ho creato un programmino che permetti di:
1) Inserire clienti
2) Ricercare un cliente

Adesso ho creato una classe Client che aveva i seguenti attributi e metodi:

cliente.h

codice:
class Client
{
	private:
			string Name;
			string Surname;
			int	Age;

	public:
			Client(string Name, string Surname, int Age);
			void setName(string Name);
			void setSurname(string Surname);
			void setAge(int Age);
			string getName();
			string getSurname();
			int getAge();
};

Mentre quest'altro è il file .cpp

codice:
// Funzione InsertClient: Funzione che mi permette di inserire un cliente
void InsertClient(Client** tmp, int &i)
{
	string name, surname;
	int age;

	cout << "This is the client number: " << i + 1 << endl;
	cout << "Insert Name: "		<< endl;
	cin >> name;
	cout << "Insert Surname: "	<< endl;
	cin >> surname;
	cout << "Insert Age: "		<< endl;
	cin >> age;
	*tmp = new Client(name, surname, age);
}

// Funzione Menu: Funzione che mi permette di gestire le operazioni dell'applicazione
bool Menu (Client* clients[], int &i)
{
	int request;

	cout << "\n\t1. Inserisci cliente: "	<< endl;
	cout << "\t2. Cerca cliente: "			<< endl;
	cout << "\t0. Esci: "					<< endl;
	cin >> request;

	switch(request)
	{
		case 1:
			{
				InsertClient(&clients[i], i);
				i++;
				break;
			}

		case 2:
			{
			
			string parameter;
			
			cout << "\nSurname of client: " << endl;
			cin >> parameter;
			bool flag = true;
			
			for (int j = 0; j < i; j++)
			{
				if (parameter == clients[j]->getSurname())
				{
					cout << "\nID client:\t"	<< j + 1;
					cout << "\nName\t:"			<< clients[j]->getName(); 
					cout << "\nSurname\t:"		<< clients[j]->getSurname();	
					cout << "\nAge:\t"			<< clients[j]->getAge() << endl;
					flag = false;
					break;
				}
			}

			if (flag == true)
				cout << "The client " << parameter << " don't exist! Try agin please";
			
			break;
			}

		case 0:
			{
			cout << "Arrivederci";
			return false;
			}

		default:
			cout << "Scelta sbagliata";

	}
	
	return true;

}

// Inizializzo il costruttore
Client::Client(std::string Name, std::string Surname, int Age)
{
	this->Name = Name;
	this->Surname = Surname;
	this->Age = Age;
}

// Le altre funzioni metodi set e get
void Client::setName(std::string Name)		{ this->Name = Name; }
void Client::setSurname(std::string Surname)	{ this->Surname = Surname; }
void Client::setAge(int Age)				{ this->Age = Age; }
string Client::getName()				{ return Name; }
string Client::getSurname()				{ return Surname; }
int Client::getAge()					{ return Age; }

// Enter Point (MAIN)
int main(int argc, char* argv[])
{
	Client* clients[100];
	int i = 0; // Numero iniziale di clienti

	while (Menu(clients, i)); // loop per il menu

	return 0;
}

Premetto che il programma funziona, però adesso vorrei capire una cosa:
Come mai devo dichiarare per forza un array di puntatori anziche un semplice array di tipo Client?
Oggi ho provato a passare alla funzione InsertClient, solamente l'elemento da riempire nell'array, ma mi dava errore.
La mia domanda è: Perchè utilizzare per forza un array di puntatori? e teoricamente come funzionano i doppi puntatori che utilizzo nei parametri formali della funzione InsertClient?

Grazie anticipatamente!