Ten kod jest bardzo brzydki i nieczytelny :(
1) Po samej strukturze i nazwach klas widać, że albo ten kod nie ma sensu, albo nie przyłożyłeś się do nazewnictwa. NameOfPlayer i NameOfOnePlayer. Oceniając po nazwie te dwie klasy są tym samym. Po co więc je dzielić? Jak zajrzałem do środka to zobaczyłem, że NameOfOnePlayer to taki wraper na poprzednią klase, który dodaje jedynie funkcjonalność otwierania i zamykania pliku. Jest to po prostu źle zaprojektowane. Po pierwsze rozdzielenie tego to przerost formy nad treścią. Za bardzo się starasz robić to ładnie obiektowo przez co wychodzi z tego po prostu nieczytelny kod. Niepotrzebnie komplikowany. Generalnie powinieneś zrobić jakiś PlayerNameFileLoader, który dostanie nazwe pliku i będzie przez jedną metodę zwracał name. Aczkolwiek jeśli cała "logika" wczytania z pliku poza jego otwarciem i zamknieciem opiera się na:
getline(file, name);
To taka klasa nie za bardzo ma nawet sens. Gdyby ten plik miał jakiś format. Chociażby "w pierwszej lini ilosc imion, w kolejnych coś tam coś tam". Wtedy byłby sens stworzyć taką klase, która na podstawie znajomości tego formatu potrafi zapisywać i odczytywać nazwiska z pliku.
Co ciekawsze klasa NameOfPlayer potrafi się sama wczytać z konsoli, ale logika wczytywania z pliku jest już w klasie drugiej.
NameOfTwoPlayers. Co dalej? NameOfThreePlayers z identycznym ciałem poza tymi linijkami?
nameOfPlayer[0].saveTo(file);
nameOfPlayer[1].saveTo(file);
nameOfPlayer[2].saveTo(file);
2) Cała zabawa z file.close() nie ma sensu, bo pliki same są zamykane w destruktorze (wywołanym po rzuceniu wyjątku) w stylu RAII:
destructs the basic_ifstream and the associated buffer, closes the file
3)
if (!file.is_open())
{
file.close();
throw CANNOT_OPEN;
}
else if (!nameOfPlayer.setFrom(file))
Jeśli chcesz rzucić wyjątek w ifie to nie potrzebujesz else:
if(somethingBadHappened)
throw exception("oh no!");
//code if everythings fine
4) Testowałeś to wgl?
std::cout << "Imie moze miec maksymalnie 12 znakow. Sprobuj jeszcze raz:";
bez przejscia do nowej lini.
5) Po co to file.get()
return getline(file, name) && file.get();
6)
void NameOfPlayer::setFromInputStream()
{
name = getFromInputStream(name);
}
Te wszystkie wywołania w tym stylu nie mają sensu. Co wnosi funkcja, która ma jedną linijke i wywołuje inną funkcję z tej samej klasy?
7)
std::string& NameOfPlayer::getFromInputStream(std::string& name) const
Bardzo zła nazwa funkcji. Brzmi jakby wczytywała z input streama a wczytuje ze standardowego wejścia (z konsoli). Input stream sugeruje różnego typu input streamy. Np istringstream czy ifstream. Obydwa sa input streamami.
8)
namespace ttt {
bez komentarza :D
9)
enum Exception { CANNOT_OPEN };
jesli używasz enumów to używaj scoped enumów i nazywaj je sensowniej. Nazwałeś go Exception, co różni się od exception tylko jedną literką, więc ktoś może pomylić, szczególnie jeśli programuje też w innych językach gdzie akurat klasy standardowe są z dużych liter. Nazwij tego enuma zgodnie z przeznaczeniem. Już zwykłe FailureType by było lepsze niż exception.
10)
const std::string nameOfFile = "nameOfOnePlayer.txt";
Cały sens tej klasy polega na wcztywaniu z pliku i nazwa pliku jest zahardkodowana w ciele? W tym momencie tworze sobie 2 obiekty tego typu i będą one sobie przeszkadzać, bo będą pisać do tego samego pliku.
Generalnie kod jest zły. Starasz sie pisać obiektowo i robić dużo metod, ale niestety niepotrzebnie gmatwasz proste rzeczy.