Разный адрес в памяти при передаче по ссылке
Не могу понять почему у меня разный адрес в памяти, если я их передаю по ссылке.
У меня MainMenu вызывает SongMenu и уже когда я попадаю в SongMenu там другой адрес переменной, хотя должен быть как в MainMenu.И получается что данные не сохраняются. Пробовал делать через указатели, но там еще хуже.
MainMenu.h
#ifndef CONCERT_MAINMENU_H
#define CONCERT_MAINMENU_H
#include <cctype>
#include <regex>
#include "Menu.h"
class MainMenu : public Menu {
private:
ConcertVotingSystem votingSystem;
ConcertProgram program;
std::unordered_map<std::basic_string<char>, int> votes;
std::vector<Song> availableSongs;
void votesForSongs();
void createProgram();
void toSummarize();
public:
// Constructor
MainMenu(ConcertVotingSystem &votingSystem, ConcertProgram &program, std::unordered_map<std::basic_string<char>, int> &votes,
std::vector<Song> &availableSongs) : Menu({
"Song menu",
"Allow users to vote for their favorite songs",
"Create a concert program based on the most popular songs",
"Display the concert program",
"Print a message indicating that voting has passed",
"Exit"
}) {
this->votingSystem = votingSystem;
this->program = program;
this->votes = votes;
this->availableSongs = availableSongs;
}
// Method to handle menu selection
void select(int selected) override;
};
#endif //CONCERT_MAINMENU_H
SongMenu.h
#ifndef CONCERT_SONGMENU_H
#define CONCERT_SONGMENU_H
#include <conio.h>
#include <limits>
#include "Menu.h"
#include "MainMenu.h"
class MainMenu;
class SongMenu : public Menu {
ConcertVotingSystem votingSystem;
ConcertProgram program;
std::unordered_map<std::basic_string<char>, int> votes;
std::vector<Song> availableSongs;
void addSong();
void updateSong();
void deleteSong();
void select(int selected) override;
public:
SongMenu(ConcertVotingSystem &votingSystem, ConcertProgram &program, std::unordered_map<std::basic_string<char>, int> &votes,
std::vector<Song> &availableSongs) : Menu({
"Add song",
"Update song",
"Delete song",
"Back"
}) {
this->votingSystem = votingSystem;
this->program = program;
this->votes = votes;
this->availableSongs = availableSongs;
}
};
#endif //CONCERT_SONGMENU_H
Реализация
MainMenu.cpp
#include <conio.h>
#include <limits>
#include "MainMenu.h"
#include "SongMenu.h"
#define NDEBUG
void MainMenu::select(int selected) {
std::cout << "Selected: " << this->getOptions().at(selected) << std::endl;
switch (selected) {
case 0: // "Add some songs and artists to the system"
system("cls");
SongMenu(votingSystem, program, votes, availableSongs).run();
_getch(); // Wait for the user to press a key
system("cls");
this->run();
break;
case 1: // Allow users to vote for their favorite songs
votingSystem.displaySongs();
votesForSongs();
_getch();
system("cls");
this->run();
break;
case 2: // Create a concert program based on the most popular songs
createProgram();
_getch();
system("cls");
this->run();
break;
case 3: // Display the concert program
#ifdef NDEBUG
printf("program : %p\n", (void*)&program);
printf("voting system : %p\n", (void*)&votingSystem);
#endif
program.display();
_getch();
system("cls");
this->run();
break;
case 4: // Print a message indicating that voting has passed
toSummarize();
_getch();
system("cls");
this->run();
break;
case 5:
exit(0);
}
}
void MainMenu::votesForSongs() {
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
bool allWhitespace = true;
std::string songName;
do {
std::cout << "\nEnter song: ";
std::getline(std::cin, songName);
for (char c: songName) {
if (!std::isspace(c)) {
allWhitespace = false;
break;
}
}
if (allWhitespace)
std::cout << "Invalid input; please re-enter." << std::endl;
} while (allWhitespace);
#ifdef NDEBUG
printf("program : %p\n", (void*)&program);
printf("voting system : %p\n", (void*)&votingSystem);
#endif
votingSystem.voteForSong(songName);
}
void MainMenu::createProgram() {
try {
availableSongs = votingSystem.getAvailableSongs();
if (availableSongs.empty()) return;
// Check if there are any votes
votes = votingSystem.getVotes();
if (votes.empty()) return;
std::sort(availableSongs.begin(), availableSongs.end(), [&](const Song& song1, const Song& song2) {
return votes[song1.getTitle()] > votes[song2.getTitle()];
});
auto it = availableSongs.begin();
for (int i = 0; i < availableSongs.size(); i++) { // Include the top 3 songs in the program
program.addSong(*it); // Dereference the iterator to get the song
++it; // Move the iterator to the next song
}
} catch (...) {
system("cls");
std::cout << "Something went wrong..." << std::flush << std::endl;
this->run();
}
}
void MainMenu::toSummarize() {
#ifdef NDEBUG
printf("program : %p\n", (void*)&program);
printf("voting system : %p\n", (void*)&votingSystem);
#endif
std::cout << "\n\nVoting has passed\n\n" << std::endl;
// Iterate through the votes unordered_map and print out each song
// title and the number of votes it received
for (auto i = votes.begin(); i != votes.end(); ++i) {
std::cout << i->first << ' ' << i->second << std::endl;
}
}
SongMenu.cpp
#include "SongMenu.h"
#define NDEBUG
void SongMenu::select(int selected) {
std::cout << "Selected: " << this->getOptions().at(selected) << std::endl;
switch (selected) {
case 0: // Add song
#ifdef NDEBUG
printf("program : %p\n", (void*)&program);
printf("voting system : %p\n", (void*)&votingSystem);
#endif
votingSystem.displaySongs();
addSong();
_getch(); // Wait for the user to press a key
system("cls");
this->run();
break;
case 1: // Update song
#ifdef NDEBUG
printf("program : %p\n", (void*)&program);
printf("voting system : %p\n", (void*)&votingSystem);
#endif
votingSystem.displaySongs();
updateSong();
_getch();
system("cls");
this->run();
break;
case 2: // Delete song
#ifdef NDEBUG
printf("program : %p\n", (void*)&program);
printf("voting system : %p\n", (void*)&votingSystem);
#endif
votingSystem.displaySongs();
deleteSong();
_getch(); // Wait for the user to press a key
system("cls");
this->run();
break;
case 3:
return;
}
}
void SongMenu::addSong() {
// Clear the input stream and ignore any leftover characters
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// Initialize variables to store user input
bool allWhitespace = true; // Flag to check if the string only contains whitespace characters
bool isValid = false; // Flag to check if the input is valid
// Prompt the user for the song name and validate the input
std::string songName;
do {
std::cout << "\nEnter song: ";
std::getline(std::cin, songName);
// Check if the string only contains whitespace characters
for (char c: songName) {
if (!std::isspace(c)) {
allWhitespace = false;
break;
}
}
// If the string only contains whitespace characters, prompt the user to re-enter
if (allWhitespace)
std::cout << "Invalid input; please re-enter." << std::endl;
} while (allWhitespace);
std::string artistName;
allWhitespace = true; // Reset the flag
do {
// Prompt the user for the artist name and validate the input
std::cout << "\nEnter artist: ";
std::getline(std::cin, artistName);
// Check if the string only contains whitespace characters
for (char c: artistName) {
if (!std::isspace(c)) {
allWhitespace = false;
break;
}
}
// If the string only contains whitespace characters, prompt the user to re-enter
if (allWhitespace)
std::cout << "Invalid input; please re-enter." << std::endl;
} while (allWhitespace);
int duration;
do { // Prompt the user for the duration of the song and validate the input
std::cout << "Enter duration of song in seconds: " << std::flush;
std::cin >> duration;
if (std::cin.good()) {
//everything went well, we'll get out of the loop and return the value
isValid = true;
} else {
//something went wrong, we reset the buffer's state to good
std::cin.clear();
//and empty it
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cout << "Invalid input; please re-enter." << std::endl;
}
} while (!isValid);
#ifdef NDEBUG
printf("program : %p\n", (void*)&program);
printf("voting system : %p\n", (void*)&votingSystem);
#endif
Song song(songName, artistName, duration);
Artist artist(artistName, {song});
votingSystem.addSong(song);
votingSystem.addArtist(artist);
}
void SongMenu::deleteSong() {
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
bool allWhitespace = true; // Flag to check if the string only contains whitespace characters
// Prompt the user for the song name and validate the input
std::string songName;
do {
std::cout << "\nEnter song: ";
std::getline(std::cin, songName);
// Check if the string only contains whitespace characters
for (char c: songName) {
if (!std::isspace(c)) {
allWhitespace = false;
break;
}
}
// If the string only contains whitespace characters, prompt the user to re-enter
if (allWhitespace)
std::cout << "Invalid input; please re-enter." << std::endl;
} while (allWhitespace);
#ifdef NDEBUG
printf("program : %p\n", (void*)&program);
printf("voting system : %p\n", (void*)&votingSystem);
#endif
votingSystem.deleteSong(songName);
}
void SongMenu::updateSong() {
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// Update the song's title, artist, and duration
bool allWhitespace = true; // Flag to check if the string only contains whitespace characters
// Prompt the user for the song name and validate the input
std::string oldTitle;
do {
std::cout << "\nEnter old song title: ";
std::getline(std::cin, oldTitle);
// Check if the string only contains whitespace characters
for (char c: oldTitle) {
if (!std::isspace(c)) {
allWhitespace = false;
break;
}
}
// If the string only contains whitespace characters, prompt the user to re-enter
if (allWhitespace)
std::cout << "Invalid input; please re-enter." << std::endl;
} while (allWhitespace);
allWhitespace = true; // Flag to check if the string only contains whitespace characters
// Prompt the user for the song name and validate the input
std::string newTitle;
do {
std::cout << "\nEnter new song title: ";
std::getline(std::cin, newTitle);
// Check if the string only contains whitespace characters
for (char c: newTitle) {
if (!std::isspace(c)) {
allWhitespace = false;
break;
}
}
// If the string only contains whitespace characters, prompt the user to re-enter
if (allWhitespace)
std::cout << "Invalid input; please re-enter." << std::endl;
} while (allWhitespace);
allWhitespace = true; // Flag to check if the string only contains whitespace characters
// Prompt the user for the song name and validate the input
std::string newArtist;
do {
std::cout << "\nEnter new artist: ";
std::getline(std::cin, newArtist);
// Check if the string only contains whitespace characters
for (char c: newArtist) {
if (!std::isspace(c)) {
allWhitespace = false;
break;
}
}
// If the string only contains whitespace characters, prompt the user to re-enter
if (allWhitespace)
std::cout << "Invalid input; please re-enter." << std::endl;
} while (allWhitespace);
bool isValid = false;
int newDuration;
do { // Prompt the user for the duration of the song and validate the input
std::cout << "Enter duration of song in seconds: " << std::flush;
std::cin >> newDuration;
if (std::cin.good()) {
//everything went well, we'll get out of the loop and return the value
isValid = true;
} else {
//something went wrong, we reset the buffer's state to good
std::cin.clear();
//and empty it
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cout << "Invalid input; please re-enter." << std::endl;
}
} while (!isValid);
#ifdef NDEBUG
printf("program : %p\n", (void*)&program);
printf("voting system : %p\n", (void*)&votingSystem);
#endif
votingSystem.updateSong(oldTitle, newTitle, newArtist, newDuration);
}
Ответы (1 шт):
Автор решения: Harry
→ Ссылка
У вас выполняется копирование переданных аргументов в локальные переменные:
this->votingSystem = votingSystem;
this->program = program;
так что выводятся у вас адреса локальных переменных, которые, само собой, отличны от переданных.
Вот вам кратенький ("минимальный" :)) пример, который все должен прояснить:
class Ref
{
int &p;
public:
Ref(int&p):p(p){}
void out() { cout << (void*)&p << endl; }
};
class Val
{
int p;
public:
Val(int&p):p(p){}
void out() { cout << (void*)&p << endl; }
};
int main(int argc, char * argv[])
{
int x = 5;
cout << (void*)&x << endl;
Ref r(x);
Val v(x);
r.out();
v.out();
}

