How do I fix "Member is ambiguous" error? - c++

I use Borland C++ 4.5 as my school recommends it.
When I try to run this code, I get three errors when I try to run the code.
I try to change the access specifier every time, but I fail.
#include "iomanip.h"
#include "iostream.h"
#include <conio.h>
#include <stdio.h>
class person
{
public:
int code;
char name[50];
void PEnter()
{
cout << "\nEnter Code :\n";
cin >> code;
cout << "\nEnter Name :\n";
gets(name);
}
};
class account : public person
{
public:
float pay;
void AcEnter()
{
cout << "\nEnter Pay :\n";
cin >> pay;
}
};
class admin : public person
{
public:
int experience;
void AdEnter()
{
cout << "\nEnter Experience :\n";
cin >> experience;
}
};
class master : public account, admin
{
public:
void MEnter()
{
PEnter();
AcEnter();
AdEnter();
}
void MRet()
{
cout << setw(20) << name << "\t" << setw(7) << code << "\t"
<< setw(6) << pay << "\t" << setw(3) << experience << "\n";
}
};
void main()
{
clrscr();
master M[200];
int i = 0;
char ch;
do {
M[i].MEnter();
++i;
cout << "\nEnter More :\n";
cin >> ch;
} while (ch == 'Y' || ch == 'y');
int j = i;
clrscr();
cout << setw(20) << "Name\t" << setw(7) << "Code\t" << setw(6)
<< "Pay\t" << setw(3) << "\tExperience\n";
for (i = 0; i <= j; ++i) {
M[i].MRet();
}
getch();
}
These are the three errors that I get:
Error NONAME00.CPP 43 : Member is ambiguous 'person::PEnter' and 'person::PEnter' in function master::MEnter()
Error NONAME00.CPP 49 : Member is ambiguous 'person::name' and 'person::name' in function master::MRet()
Error NONAME00.CPP 49 : Member is ambiguous 'person::code' and 'person::code' in function master::MRet()
I do not know whether the class person is being inherited or not (by the master class).

You hit the diamond inheritance problem. What it is and how to solve it described here virtual inheritance Note inheritance in the wiki example is very close to yours so there should not be any problem for you to follow solution provided there

One can also inherit the base class as virtual
class admin : public virtual person
class account : public virtual person

call the fn as
person::PEnter();
input the value like this -
person::name;
person::code;

Related

Basic methods to prevent C++ program to crash

I am new to programming and just shifted to C++ from C.
I was learning the concepts of inheritance and tried to make a simple application that takes input from the user and show that data on consol, But I am facing some problems running it.
My program seems syntactically correct but it crashes frequently. So I wondered if anyone can teach me what to take into consideration while writing the program to prevent those crashes.
here is my sample code
/*
Define a class Hospital having rollno and name as data members and member function to
get and print data.
Derive a class Ward from class Hospital having data members: ward number and member function to get and print data.
Derive another class Room from Hospital having data member bed number and nature of illness and member function to get and print data.
Derive class Patient from Class Ward and Class Room.
In main () declare 5 object of Class Patient and get and display all the information.
Use the concept of Virtual Base Class and Hybrid Inheritance.
*/
#include <iostream>
#include <string>
using namespace std;
class Hospital
{
int rollno;
string name;
public:
void get()
{
cout << "Enter the roll number : ";
cin >> rollno;
fflush(stdin);
cout << "Enter the name :";
fflush(stdin);
getline(cin, name);
fflush(stdin);
}
void print()
{
cout << "\nRoll No : " << rollno;
cout << "\nName : " << name;
}
};
class Ward : public virtual Hospital
{
int W_number;
public:
void get()
{
// Hospital :: get();
cout << "Enter the Ward number : ";
cin >> W_number;
}
void print()
{
cout << "\nWard number : " << W_number;
}
};
class Room : virtual public Hospital
{
int bedNumber;
string natureOfIllness;
public:
void get()
{
cout << "Enter the bed number of patient : ";
cin >> bedNumber;
fflush(stdin);
cout << "Enter the nature of illness : ";
fflush(stdin);
getline(cin, natureOfIllness);
}
void print()
{
cout << "\nBed Number : " << bedNumber;
cout << "\nNature of illness : " << natureOfIllness;
}
};
class Patient : public Ward, public Room
{
public:
void get()
{
Hospital::get();
Ward::get();
Room::get();
}
void print()
{
cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n";
Hospital::print();
Ward::print();
Room::print();
cout << "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n";
}
};
int main()
{
Patient p[5];
for (int i = 0; i < 5; i++)
{
cout << "\n\nEnter informtion of patient " << i + 1 << endl;
p[i].get();
}
for (int i = 0; i < 5; i++)
{
cout << "Informtion of patient " << i + 1 << endl;
p[i].print();
}
return 0;
}
thank you.
When you inherit from a class you need to make the destructor virtual
So Hospital should have a virtual destructor.
If you want to override functions declare them virtual in the base class
virtual void get();
virtual void print();
otherwise you are hiding the functions/
Always initialize all member variables
Just write
class Ward : public Hospital {...}
But the fundamental problem with your code is that using Hospital as base
class doesn't make sense, a Ward is not a kind of Hospital
You should instead treat the Hospital as a container, so called composition.
The Hospital contains one or more wards so use Hospital as the container, containing a Wards have Rooms, Rooms have Patients,
Now if you want to have the same behavior in all your classes you could create an interface for get/set for instance and use that instead to inherit from.
struct IGetPrint
{
virtual void get() = 0;
virtual void print() = 0;
~IGetPrint() = default;
};
class Hospital : public IGetPrint
{
public:
void get() override
{
std::cout << "Enter the roll number : ";
std::cin >> rollno;
std::cout << "Enter the name :";
std::getline(std::cin, name);
}
void print() override
{
std::cout << "\nRoll No : " << rollno;
std::cout << "\nName : " << name << std::flush;
}
protected:
int rollno{0};
std::string name;
};
// side note, do not use fflush(stdin) use cin.ignore instead
// otherwise you will undefined behavior
try using void main() instead of int main and end it with getch() with using #include<stdlib.h>
it might help you out
sometimes I used to face this type of problem and got sorted by doing that

C++: Multiple definition of object error

I recently started with file structuring in C++ with little success. The project was split into following files
-groups.h
-groups.cpp
-people.h
-people.cpp
-main.cpp
There are 2 base classes, groups and players and every other class in inherited by either of them.
Here's the files
groups.h
people.h
groups.cpp
people.cpp
main.cpp
groups.h
#ifndef GROUPS_H
#define GROUPS_H
//Groups of people one of the base classes
class groups {
int num_of_people;
float avg_age;
friend class SoccerTeams;
public:
//virtual string getclass() { return char2str(typeid(*(this)).name()); }
groups(int numb = 0): num_of_people(numb) {};
~groups(){};
};
//SoccerTeam group class
class SoccerTeams : public groups {
std::string teamName;
std::vector<SoccerTeams> teams;
int teamId;
public:
Players player;
void addManager();
std::string nameTeam(int);
void deletePlayer(int);
void showTeam();
void addPlayer();
void showPlayers();
void showManagers();
void exportToFile(const char *);
SoccerTeams() {};
SoccerTeams(std::string, int);
~SoccerTeams() {};
};
//FanClub group class
class FanClubs : public groups{
std::string clubName;
int clubId;
std::vector<FanClubs> fanclubs;
public:
Fans fan;
void addFans();
void showFans();
FanClubs() {};
FanClubs(std::string, int);
~FanClubs() {};
};
#endif
groups.cpp
#include <algorithm>
#include <iostream>
#include <vector>
#include <typeinfo>
#include <boost/units/detail/utility.hpp>
#include <cstdlib>
#include <fstream>
#include <list>
#include "groups.h"
using namespace std;
//Fan Club member functions
FanClubs::FanClubs(string name, int id) {
clubName = name;
clubId = id;
fanclubs.push_back(*this);
};
void FanClubs::showFans() {
cout << "Players in " << fanclubs.begin() -> clubName << endl;
fan.showFanas();
}
void FanClubs::addFans() {
int choice = 0;
cout << "1. Add a bunch of fans\n2. Add custom fans\nChoice: ";
cin >> choice;
switch(choice) {
case 1: {
int requirement;
cout << "How many fans do you need: ";
cin >> requirement;
static const string names[] = {
"Margarita", "Amalia", "Sam", "Mertie", "Jamila", "Vilma",
"Mazie", "Margart", "Lindsay", "Kerstin", "Lula", "Corinna", "Jina",
"Jimmy", "Melynda", "Demetrius", "Beverly", "Olevia", "Jessika",
"Karina", "Abdallah", "Max", "Prateek", "Aghaid"
};
for (int i = 0; i < requirement; ++i) {
fan.name = names[rand() % 24];
fan.age = (rand() % 80 + 1);
fan.sex = ((rand() % 2) ? 'M' : 'F');
fan.under_auth = false;
fan.auth_level = 0;
fans.push_back(fan);
}
break;
}
case 2: {
int requirement;
cout << "How many fans you want to add?\nnumber: ";
cin >> requirement;
for (int i = 0; i < requirement; ++i) {
cout << "======Fan " << i + 1 << "=======\n";
cout << "Enter name: ";
cin >> fan.name;
cout << "Enter age: ";
cin >> fan.age;
cout << "Enter sex: ";
cin >> fan.sex;
fan.under_auth = false;
fan.auth_level = 0;
fans.push_back(fan);
}
break;
}
default:
cout << "Incorrect choice\n";
break;
}
}
//Soccer Teams member functions
string SoccerTeams::nameTeam(int id) {
return teams.begin() -> teamName;
}
void SoccerTeams::showPlayers() {
cout << "Players in " << teams.begin() -> teamName << endl;
player.showPlayas();
}
void SoccerTeams::showManagers() {
int counter = 1;
list<ManagingDirectors>::iterator i;
for (i = directors.begin(); i != directors.end(); i++) {
cout << "Director " << counter << endl;
cout << "Works for team " << nameTeam(i -> directorId) << endl;
cout << "Name: " << i -> name << endl;
cout << "Sex: " << i -> sex << endl;
counter++;
}
}
void SoccerTeams::addPlayer() {
int newId;
int number;
cout << "Number of players to be added: ";
cin >> number;
for (int i = 0; i < number; ++i) {
cout << "\nEnter player name: ";
cin >> player.name;
cout << "Enter sex(M/F): ";
cin >> player.sex;
cout << "Enter age: ";
cin >> player.age;
cout << "Enter player id(0 for random id): ";
cin >> newId;
newId == 0 ? player.playerId = (rand() % 100 + 1) : player.playerId = newId;
player.under_auth = true;
player.auth_level = 0;
players.push_back(player);
teams.begin()->num_of_people++;
}
}
void SoccerTeams::deletePlayer(int id) {
std::vector<Players>::iterator i;
for (i = players.begin(); i != players.end(); ) {
if(i->playerId == id) {
i = players.erase(i);
teams.begin()->num_of_people--;
}
else
i++;
}
}
void SoccerTeams::showTeam() {
vector<SoccerTeams>::iterator i;
for (i = teams.begin(); i != teams.end(); ++i) {
cout << "\nTeam name: " << i -> teamName << endl;
cout << "Team id: " << i -> teamId << endl;
cout << "Number of players: " << i -> num_of_people << endl;
cout << "Average age: " << i -> player.ageCalc()/teams.begin() -> num_of_people << endl;
}
}
SoccerTeams::SoccerTeams(string tn, int id) {
teamName = tn;
teamId = id;
teams.push_back(*this);
};
void SoccerTeams::addManager() {
ManagingDirectors mandir;
int number;
cout << "How many managers you want to add: ";
cin >> number;
for (int i = 0; i < number; i++) {
cout << "Manager " << i + 1 << endl;
cout << "Enter name of the director: ";
cin >> mandir.name;
cout << "Enter the age: ";
cin >> mandir.age;
cout << "Enter the sex(M/F): ";
cin >> mandir.sex;
mandir.directorId = teams.begin() -> teamId;
mandir.auth_level = 3;
mandir.under_auth = false;
directors.push_front(mandir);
}
}
void SoccerTeams::exportToFile(const char *filename) {
ofstream outfile;
outfile.open(filename, ios::out);
vector<Players>::iterator i;
int counter = 1;
outfile << "Team Data" << endl;
outfile << "Team name : " << teamName << "\nPlayers : " << teams.begin() -> num_of_people << endl;
outfile << "Average age: " << teams.begin() -> player.ageCalc()/teams.begin() -> num_of_people << endl;
for (i = players.begin(); i != players.end(); ++i) {
outfile << "\nPlayer " << counter << endl;
outfile << "Name: " << i -> name << endl;
outfile << "Sex : " << i -> sex << endl;
outfile << "Age : " << i -> age << endl;
outfile << "Pid : " << i -> playerId << endl;
counter++;
}
outfile.close();
}
people.h
#ifndef PEOPLE_H
#define PEOPLE_H
//People base class
class people {
string name;
char sex;
int age;
bool under_auth;
int auth_level;
friend class SoccerTeams;
friend class Players;
friend class Fans;
friend class FanClubs;
public:
//virtual string getclass() { return char2str(typeid(*(this)).name()); }
people(){};
~people(){};
//virtual int get_age(){ return this->age; };
};
//players class people
class Players : public people {
int playerId;
int avgAge;
friend class SoccerTeams;
public:
void showPlayas();
float ageCalc();
Players(){};
~Players(){};
};
std::vector<Players> players;
//Class Managing Directors people
class ManagingDirectors : public people {
int directorId;
friend class SoccerTeams;
public:
ManagingDirectors(int);
ManagingDirectors() {};
~ManagingDirectors(){};
};
std::list<ManagingDirectors> directors;
//Fans people class
class Fans : public people {
public:
void showFanas();
Fans(){};
~Fans(){};
};
std::vector<Fans> fans;
#endif
people.cpp
#include <algorithm>
#include <iostream>
#include <vector>
#include <typeinfo>
#include <boost/units/detail/utility.hpp>
#include <cstdlib>
#include <fstream>
#include <list>
#include "people.h"
using namespace std;
const int vector_resizer = 50;
string char2str(const char* str) { return boost::units::detail::demangle(str); }
//Fan class member functions
void Fans::showFanas() {
int counter = 1;
vector<Fans>::iterator i;
for (i = fans.begin(); i != fans.end(); ++i) {
cout << "\nFan " << counter << endl;
cout << "Name: " << i -> name << endl;
cout << "Sex: " << i -> sex << endl;
cout << "Age: " << i -> age << endl;
counter++;
}
}
//Players class member functions
float Players::ageCalc() {
int totalAge = 0;
vector<Players>::iterator i;
for (i = players.begin(); i != players.end(); ++i) {
totalAge += i->age;
}
return totalAge;
}
void Players::showPlayas() {
int counter = 1;
vector<Players>::iterator i;
for (i = players.begin(); i != players.end(); ++i) {
cout << "\nPlayer " << counter << endl;
cout << "Name: " << i -> name << endl;
cout << "Sex: " << i -> sex << endl;
cout << "Age: " << i -> age << endl;
cout << "Player id: " << i -> playerId << endl;
counter++;
}
}
//Member functions of Managing DIrectos
ManagingDirectors::ManagingDirectors(int number) {
directorId = number;
};
In addition to these files, I also have a makefile.
//makefile
footballmaker: main.o groups.o people.o
gcc -o main main.o groups.o people.o
rm groups.o people.o
Also here's all the code in one file, the way it works right now.
I'm getting the following error when I try to make the program,
gcc -o main main.o groups.o people.o
groups.o:(.bss+0x0): multiple definition of `players'
main.o:(.bss+0x0): first defined here
groups.o:(.bss+0x20): multiple definition of `directors[abi:cxx11]'
main.o:(.bss+0x20): first defined here
groups.o:(.bss+0x40): multiple definition of `fans'
main.o:(.bss+0x40): first defined here
people.o:(.bss+0x0): multiple definition of `players'
main.o:(.bss+0x0): first defined here
people.o:(.bss+0x20): multiple definition of `directors[abi:cxx11]'
main.o:(.bss+0x20): first defined here
people.o:(.bss+0x40): multiple definition of `fans'
main.o:(.bss+0x40): first defined here
...
collect2: error: ld returned 1 exit status
makefile:3: recipe for target 'footballmaker' failed
make: *** [footballmaker] Error 1
The entire error was over 400 lines long, it is attached here.
I'm not sure how I can include files, so that I don't duplicate them, since the files are needed to make the program work, would there be a better way to split my code into files?
You define (not just declare!) variables at file scope in header file people.h. Such a variable definition will be visible to all other translation units at time of linkage. If different translation units, e.g. people.cpp and main.cpp, now include people.h, then this is as if these variable definitions had been written directly into both people.cpp and main.cpp, each time defining a separate variable with the same name at a global scope.
To overcome this, declare the variables in the header file, but define it in only one translation unit, e.g. people.cpp. Just declaring a variable means putting keyword extern in front of it (telling the compiler that variable definition will be provided by a different translation unit at the time of linking):
// people.h
extern std::vector<Players> players;
extern std::list<ManagingDirectors> directors;
extern std::vector<Fans> fans;
// people.cpp
std::vector<Players> players;
std::list<ManagingDirectors> directors;
std::vector<Fans> fans;

C++ Error (operand types are 'std::string and 'void')

1st of all Im newBee at C++ programming.so please apologize if i make lots of mistake while asking questions.
My problem is:
i create class which contain private variable and Methods like below:
class Records{
private:
string name;
public:
string n;
void setValue(){
cout << "Enter name" << endl;
cin >> name;
}
void getValue(){
n = name;
cout << "Name is: " << n << endl;
}
};
I have run your code on GCC compiler, it's successfully worked. Please, see complete example :
#include <iostream>
using namespace std;
class Records{
private:
string name;
public:
string n;
void setValue(){
cout << "Enter name" << endl;
cin >> name;
}
void getValue(){
n = name;
cout << "Name is: " << n << endl;
}
};
int main()
{
Records r;
r.setValue();
r.getValue();
}

Error Variable is Protected

#include <iostream>
#include <string>
#include <cstdlib>
#include <ctime>
using namespace std;
void armySkirmish();
void battleOutcome();
string commander = "";
int numberOfHumans = 0;
int numberOfZombies = 0;
class ArmyValues
{
protected:
double attackPower;
double defensePower;
double healthPoints;
public:
void setAttackPower(double a)
{
attackPower = a;
}
void setDefensePower(double d)
{
defensePower = d;
}
void setHealthPoints(double h)
{
healthPoints = h * (defensePower * .1);
}
};
class Zombies: public ArmyValues
{
};
class Humans: public ArmyValues
{
};
int main(int argc, char ** argv)
{
cout << "Input Commander's Name: " << endl;
cin >> commander;
cout << "Enter Number of Human Warriors: " << endl;
cin >> numberOfHumans;
cout << "Enter Number of Zombie Warriors: " << endl;
cin >> numberOfZombies;
armySkirmish();
battleOutcome();
return 0;
}
void armySkirmish()
{
cout << "\nThe Humans tense as the sound of the undead shuffle towards them." << endl;
cout << commander << " shuffles forward with a determined look." << endl;
cout << "The undead form up into ranks and growl a war chant!" << endl;
cout << commander <<" shouts, CHARGE!!!" << endl;
cout << endl;
cout << "Warriors from both sides blitz across the field!" << endl;
cout << endl;
cout << "*The Carnage has begun!*" << endl;
cout << "*Steal, Sparks, and Flesh flies" << endl;
}
void battleOutcome()
{
int zombieLives = numberOfZombies;
int humanLives = numberOfHumans;
int randomNumber = 0;
int humanDeath = 0;
int zombieDeath = 0;
double newHumanLife = 0;
double newZombieLife = 0;
Zombies zombieBattleData;
Humans humanBattleData;
srand(time(NULL));
zombieBattleData.setAttackPower(20.0);
humanBattleData.setAttackPower(35.0);
zombieBattleData.setDefensePower(15.0);
humanBattleData.setDefensePower(20.0);
zombieBattleData.setHealthPoints(150.0);
humanBattleData.setHealthPoints(300.0);
while(zombieLives && humanLives > 0)
{
randomNumber = 1+(rand()%10);
if(randomNumber < 6)
{
newHumanLife = humanBattleData.healthPoints - zombieBattleData.attackPower;
if(newHumanLife <= 0)
{
humanLives--;
humanDeath++;
}
}else
{
newZombieLife = zombieBattleData.healthPoints - humanBattleData.attackPower;
if(newZombieLife <= 0)
{
zombieLives--;
zombieDeath++;
}
}
}
if(zombieLives <= 0)
{
cout << "Humans have emerged victorious!" << endl;
cout << "Human Deaths: " << humanDeath << "Zombie Deaths: " << zombieDeath << endl;
}else if(humanLives <= 0)
{
cout << "Zombies have emerges victorious!" << endl;
cout << "Human Deaths: " << humanDeath << "Zombie Deaths: " << zombieDeath << endl;
}
I know the code wont run properly as of now. What I was doing was a test run to make sure I was receiving no errors. The two errors I'm getting are:
armySimulatorMain.cpp:25:10: error: 'double ArmyValues::healthPoints' is protected
armySimulatorMain.cpp:115:67: error: within this context.
newHumanLife = humanBattleData.healthPoints - zombieBattleData.attackPower;
This is the case for Attack Power and Health Power however, Defense power is clearing the errors. i don't understand why they are getting flagged. I'm changing the variable through the public function so shouldn't this be allowed?
Also, I'm calling three variables outside of all functions because they are being used by multiple functions. How can I plug those variables somewhere I don't like that they are floating freely above everything?
Thanks guys I can't believe I forgot about getters... Anyway the code runs now much appreciated I'll make sure to remember this time xD
It's not complaining about the line where you set the values; as you say, that uses a public function. But here, you try to read the protected member variables:
newHumanLife = humanBattleData.healthPoints - zombieBattleData.attackPower;
You only try to read two variables, and those are the ones it complains about.
You'll need a public getter function to read the values.
You need to do something like:
public:
double gethealthPoints()
{
return healthPoints;
}
because attackPower, defensePower, healthPoints are all protected, so if you want to access to any of them you need a getter, otherwise you will always receive an protect error

C++ class multiple inheritance error

I have been working on multiple inheritance. I have made a program but it keeps giving me an error such as Human::getInfo is ambiguous. How do I solve the problem
here is my code
#include <iostream>
#include <string>
using namespace std;
class Man{
protected:
std::string name;
public:
void getInfo(string hName){
name = hName;
}
void showInfo(){
std::cout << "Your name is: " << name << std::endl;
std::cout << "And you are a MAN" << std::endl;
}
};
class Women:public Man{
public:
Women(){}
void Women_showInfo(){
std::cout << "Your name is: " << name << std::endl;
std::cout << "And you are a Women" << std::endl;
}
};
class Human:public Women, public Man{
public:
Human(){}
};
int main(){
//local variables
string choice;
string name;
//class object
Human person;
//user interface
cout << "What your name: " ;
cin >> name;
cout << "Are you a [boy/girl]: ";
cin >> choice;
//saving name
person.getInfo(name); //ambiguous
//if handler
if (choice == "boy"){
person.showInfo(); //ambiguous
}else if(choice == "girl"){
person.Women_showInfo(); //works fine no error
}
system("pause");
return 0;
}
Also feel free to make changes in my code and would be even better if your could point out my mistake using my code.
Your design is rather questionable, but the particular ambiguity arises because Human inherits from both Woman and Man, but Woman already inherits from Man.
So Human has two getinfo() functions in it - Human::Man::getinfo() and Human::Woman::Man::getinfo(). Unless you tell the compiler which one to use it doesn't know, and thus reports an error.