c++ method parameters giving unexpected output - c++

Main class code:
#include <iostream>
#include "Chair.h"
using namespace std;
int main()
{
cout << "Hello world!" << endl;
Chair c1;
c1.chairType("Olivia",4,32,true); // not working
Chair c2;
c1.chairType("Stephano",8,8,false);
return 0;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Header class code:
#ifndef CHAIR_H_INCLUDED
#define CHAIR_H_INCLUDED
#include <iostream>
using namespace std;
class Chair
{
private:
int legCount;
int height;
bool cushioned;
string name;
public:
void chairType(string newName, int newLegCount, int newHeight, bool cush);
};
#endif // CHAIR_H_INCLUDED
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Chair.cpp class:
#include <iostream>
#include "Chair.h"
using namespace std;
void Chair::chairType(string newName, int newLegCount, int newHeight, bool cush)
{
name=newName;
legCount=newLegCount;
newHeight=newHeight;
cushioned=cush;
cout<<"I'm a chair, the following are my specs: "<<endl;
cout<<"Model: "<<name<<endl;
cout<<"Num of Legs: "<<legCount<<endl;
cout<<"Height: "<<height<<endl;
cout<<"Cushioned? : "<<cush<<endl;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Output for the four variables fed into the method is as expected, apart from the third variable (second int) which is printing as being 2752192 regardless of what I feed to it, and for both objects c1 and c2.
I'm new to C++. I've been practising some object class questions trying to familiarise myself with the syntax. I vaguely understand pointers can cause reference addresses to print on occasion. However, this 7 digit number doesn't appear to be in address format. I've done some searches and can't see a similar question. If there is one, I would appreciate direction to it. I don't wish to break the terms of posting here on the site. Thank you in advance for your assistance.

newHeight=newHeight;
should be replaced with
height=newHeight;
but better you should initialize object in constructor, rather than separate method:
class Chair
{
private:
int legCount;
int height;
bool cushioned;
string name;
public:
Chair( const string &newName, int newLegCount, int newHeight, bool cush) :
legCount( newLegCount ),
height( newHeight ),
cushioned( cush ),
name( newName )
{
}
...
};
int main()
{
cout << "Hello world!" << endl;
Chair c1("Olivia",4,32,true); // works now
Chair c2("Stephano",8,8,false);
return 0;
}
this way you cannot have instance of your class uninitialized and your mistake also would be detected by compiler.

Here is the mistake in your implementation Chair.cpp:
newHeight=newHeight;
This is the correct:
height = newHeight;
The long number you get is the uninitialized value of member variable height in your Chair object.

Related

Nothing prints; do I need a main or should it work without it, theoretically?

I'd hate to ask this but I've been trying this for HOURS and I can't figure it out. I'm brand new to C++ and can't figure out why the sprintf_s won't put anything out at the end (or both of them for that matter). Basically, nothing happens in Visual Studio 2019 except the window pops up. I know it's a simple solution but I am going crazy trying to figure it out. Also, do I HAVE to have a main or should it work without it? Ok, also, does my constructor look ok? I have the green squiggly under it and not sure how to fix it or if I can ignore that. I appreciate all the help I can get! Thank you!
//#include "stdafx.h" - commented out as I think this version of VS does
//this automatically (I looked under precompiled headers and it was listed as "Precompiled Header File"
//and it wouldn't work unless I commented it out
#include <iostream>
using namespace std;
// Base Entree class
class Entree
{
protected:
char _entree[10];
public:
const char* getEntree()
{
return _entree;
}
};
// Base Side class
class Side
{
protected:
char _side[10];
public:
char* getSide()
{
return _side;
}
};
class Drink
{
protected:
char _drink[10];
public:
Drink()
{
cout << "\n Fill cup with soda" << endl;
strcpy_s(_drink, "soda");
}
char* getDrink()
{
return _drink;
}
};
// ADDED CODE:
class ComboMeal
{
private:
Entree* entree;
Side* side;
Drink* drink;
char _bag[100];
public:
ComboMeal(const char* type)
{
sprintf_s(_bag, "/n %s meal combo: ", type);
}
void setEntree(Entree * e)
{
entree = e;
}
void setSide(Side * s)
{
side = s;
}
void setDrink(Drink * d)
{
drink = d;
}
const char* openMealBag()
{
sprintf_s(_bag, "%s, %s, %s, %s", _bag, entree->getEntree(), side->getSide(), drink->getDrink());
return _bag;
}
};
int main()
{
}
As it's been said in the comments, in C++ the code that's executed is the one in the main function. Constructors are called when objects of the correspondent class are created, so you should at least have something like this:
int main(){
ComboMeal combo("my type one");
return 0;
}
A more complete example would be:
int main(){
ComboMeal combo("my type one");
combo.setEntree(new Entree);
combo.setSide(new Side);
combo.setDrink(new Drink);
cout << combo.openMealBag() << endl;
return 0;
}
(Of course this will print garbage, because the values within the new objects are not set)

Segmentation Fault in memcpy operation of a struct

I am adding the header file and cpp file (it has main fucntion).
AuctionPrices.h
#ifndef AuctionPrices_h
#define AuctionPrices_h
/*
*
* class AuctionPrices - maintains Buy Order, Sell Order books
*/
#include <bits/stdc++.h>
#include <map>
//#pragma pack(1)
struct Order
{
char * itemId;
char * auctionId;
int Side;
};
class AuctionPrices
{
public:
virtual int AddNewOrder(char *itemId, char *auctionId, int Side, int Price) = 0;
virtual int DeleteOrder(char *itemId, char *auctionId) = 0;
virtual int Print() = 0;
};
class AuctionPrice_Imp : public AuctionPrices
{
public:
AuctionPrice_Imp();
~AuctionPrice_Imp();
std::map <int, Order, std::greater< int >> BuyMap;
std::map <int, Order, std::less< int >> SellMap;
int AddNewOrder(char *itemId, char *auctionId, int Side, int Price);
int DeleteOrder(char *itemId, char *auctionId);
int Print();
};
#endif
AuctionPrices_Imp.cpp
/**
* Auction Price Class implementation
* Constructor, AddNewOrder, DeleteOrder, Print
*
*/
#include <bits/stdc++.h>
#include <map>
#include "AuctionPrices.h"
using namespace std;
AuctionPrice_Imp::AuctionPrice_Imp()
{
}
AuctionPrice_Imp::~AuctionPrice_Imp()
{
}
int AuctionPrice_Imp::AddNewOrder(char *itemId, char *auctionId, int Side, int Price)
{
Order order;
memcpy(order.itemId, itemId, strlen(itemId)+1);
memcpy(order.auctionId, auctionId, strlen(auctionId)+1);
order.Side = Side;
if (Side == 1)
{
BuyMap.insert (std::pair<int,Order>(Price,order));
//buyLevels_.insert( std::pair< OfPrice, Level< OrderEntry > >( price, buyLevel ) );
}
else if (Side == 2)
{
SellMap.insert (std::pair<int,Order>(Price,order));
}
else
{
return 0;
}
return 1;
}
int AuctionPrice_Imp::DeleteOrder(char *itemId, char *auctionId)
{
return 0;
}
int AuctionPrice_Imp::Print()
{
std::map <int,Order,std::greater< int >>::iterator buy_it;
std::map <int,Order,std::less< int >>::iterator sell_it;
// Print Sell Map
for ( sell_it = SellMap.begin();sell_it != SellMap.end(); sell_it++)
{
std::cout << sell_it->first << '\t' << std::endl;
}
// Print Buy Map
for ( buy_it = BuyMap.begin();buy_it != BuyMap.end(); buy_it++)
{
std::cout << buy_it->first << '\t' << std::endl;
}
return 1;
}
int main()
{
AuctionPrice_Imp * auctionPrice_Imp = new AuctionPrice_Imp();
/*
AddNewOrder(“item1”, “auction1”, 1, 100)
AddNewOrder(“item1”, “auction2”, 1, 101)
AddNewOrder(“item2”, “order3”, 1, 99)
AddNewOrder(“item2”, “order4”, 2, 100)
*/
auctionPrice_Imp->AddNewOrder("item1", "auction1", 1, 100);
auctionPrice_Imp->AddNewOrder("item1", "auction2", 1, 101);
auctionPrice_Imp->AddNewOrder("item2", "order3", 1, 99);
auctionPrice_Imp->AddNewOrder("item2", "order4", 2, 100);
auctionPrice_Imp->Print();
}
When I am running the code its giving segmentation fault at the line:
memcpy(order.auctionId, auctionId, strlen(auctionId)+1);
Please anyone can help or correct the code.
The functions I am calling are supposed to add the orders to the Maps: BuyMap and SellMap. Once they have added to those map, I am using a print function to print the values.
Order order;
This creates a new Order object. Order does not have a constructor, so none of its class members, itemId, and auctionId, get initialized to point to anything. These pointers are uninitialized, random garbage. Immediately afterwards:
memcpy(order.itemId, itemId, strlen(itemId)+1);
memcpy(order.auctionId, auctionId, strlen(auctionId)+1);
Since neither itemId, nor auctionId, point to sufficient memory that are at least strlen(itemId)+1 or strlen(auctionId)+1 in size, respectively, this results in undefined behavior, and your crash.
In C++, before using a pointer, it is your responsibility to make sure that the pointer is valid, and points to the correct object, objects, or sufficiently-sized memory buffers. C++ will not do that for you, you have to do all that work yourself.
But if your intent is to write modern C++ code, it is much simpler just to use C++ classes, like std::strings instead of plain char * pointers. std::strings automatically handle all these low-level details, manage memory properly, without making it your responsibility to do so. You will find a complete description of std::string and many examples of using it in your C++ textbook.
You should use std::string to avoid having to deal with low level issues of pointers and memory allocation. These are the issues that you are getting wrong in your code. Here's your code rewritten to use std::string
struct Order
{
std::string itemId;
std::string auctionId;
int Side;
};
int AuctionPrice_Imp::AddNewOrder(std::string itemId, std::string auctionId, int Side, int Price)
{
Order order;
order.itemId = itemId;
order.auctionId = auctionId;
order.Side = Side;
See how easy that is? The code to use std::string is no different to the code that handles int.

How to pass data through MVC for C++ (possibly using vectors or pointers)

So I have a project in which I must parse a data file, and dynamically create instances of a class Sensor while passing in the parsed data to that class. I am storing these instances in a vector of object pointers, sensors. Once the data is passed into each instance of Sensor, inside the Sensor class I must generate a reading value using the min and max values passed in from the parser. Then all of the values, min, max, type, reading, material, id must be passed to a controller class called SensorMount . This class is responsible for routing the data to a DisplayDeviceclass that I have not yet implemented.
I am confused on how to implement my controller SensorMount class. I know I need to use my get functions in the Sensor class, but I just am not sure where to start with this. Would another vector of Sensor object instances work? That is my current idea but I'm not sure if that is possible. I know sending a "message object" (Stated by my prof) could work but I can't seem to find any implementation of one online. I really appreciate any help and patience, I'm new to this and feel really stuck.
Also, I see alot of people on stack overflow condemn the use of using namespace but my professor wants us to use it. And we are not to implement a design pattern for this program (I know observer would work) , we will do that in the next.
Simulation.cpp (Where data parser is called and vector is created and initial data is passed )
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <stdio.h>
#include "Simulation.hpp"
#include "EnviroSimDataParser.h"
Simulation::Simulation() {}
Simulation::~Simulation(){}
void Simulation::initializeSimulation() {
char fileName[64];
char m_sType[64];
char m_sMaterial[64];
int m_iID;
char m_sUnits[64];
double m_sMinVal;
double m_sMaxVal;
char type[64];
int IDs[8];
int IDCount;
cout << "Enter the name of the data file:" << endl;
cin >> fileName ;
//cout << fileName << "\n" ;
parser = new EnviroSimDataParser(fileName);
for (int i = 0; i < 6; i++){
parser ->getSensorData(m_sType, m_sMaterial, &m_iID, m_sUnits, &m_sMinVal, &m_sMaxVal);
sensors.push_back(new Sensor(m_sType, m_sMaterial, m_iID, m_sUnits, m_sMinVal, m_sMaxVal));
cout << "success " << m_iID << endl;
}
for (int x = 0; x <4; x++){
parser -> getDisplayData(type, IDs, &IDCount);
//if (strcmp(type, ""))
}
mount = new SensorMount();
display = new Display();
}
void Simulation::runSimulation(){
}
Sensor.cpp
#include "Sensor.hpp"
Sensor::Sensor(char *SensorType, char *SensorMaterial, int SensorID, char *SensorUnit, double MaxVal, double MinVal) {
strcpy(type, SensorType);
strcpy(material, SensorMaterial);
ID = SensorID;
strcpy(unit, SensorUnit);
max = MaxVal;
min = MinVal;
}
Sensor::Sensor(){}
Sensor::~Sensor()
{
}
double Sensor::generateReading(){
reading = min + (rand() % (int)(max - min + 1));
cout << reading<< endl;
return reading;
}
char * Sensor::getType(){
return type;
}
char * Sensor::getMaterial(){
return material;
}
int Sensor::getID(){
return ID;
}
char * Sensor::getUnit(){
return unit;
}
double Sensor::getMin(){
return min;
}
double Sensor::getMax(){
return max;
}
double Sensor::getReading(){
return reading;
}
//void Sensor::sendSensorData(){
// SensorMount.routeData(Display)
//}
Sensor.h
#ifndef Sensor_hpp
#define Sensor_hpp
#include <stdio.h>
#include <iostream>
#include <fstream>
using namespace std;
class Sensor
{
public:
Sensor();
Sensor(char *SensorType, char *SensorMaterial, int SensorID, char *SensorUnit, double MaxVal, double MinVal);
~Sensor();
//virtual Sensor updateSensor();
char * getType();
char * getMaterial();
int getID();
char * getUnit();
double getMin();
double getMax();
double getReading();
private:
char type[32];
char material[32];
int ID;
int reading;
char unit[32];
double min;
double max;
double generateReading();
};
#endif /* Sensor_hpp */
SensorMount.h (controller)
#ifndef SensorMount_hpp
#define SensorMount_hpp
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <vector.
#include "Sensor.hpp"
#include "Display.hpp"
using namespace std;
class SensorMount{
private:
Sensor *sensors;
Display *displayDevices;
vectorgetSensorData;
public:
SensorMount();
~SensorMount();
};
#endif /* SensorMount_hpp */

Accessor Method to view private variable based on argument in a class in c++?

My problem is that I have many variables in my class and I want them to be accessed via an accessor method. Of course I could have several accessor functions to output my private variables but how can I make it so I can access any of them via an argument. My class:
class Character {
public:
void setAttr(string Sname,int Shealth,int SattackLevel,int SdefenseLevel) {
name = Sname;
health = Shealth;
attackLevel = SattackLevel;
defenseLevel = SdefenseLevel;
}
int outputInt(string whatToOutput) {
return whatToOutput //I want this to either be health, attackLevel or defenseLevel
}
private:
string name;
int health;
int attackLevel;
int defenseLevel;
};
Basically what I want to know is how do I return a private variable in regards to the outputInt function. Most OOP tutorials have one function to return each variable which seems like a very unhealthy thing to do in a large program.
C++ doesn't support what you try to accomplish: reflection or detailed runtime information about objects. There is something called "Run-Time Type Information" in C++, but it can't provide information about your variable name: the reason is because, in the compiled and linked binary this information (names of your variables) will not be necessarily present anymore.
However, you can accomplish something close to that, using i.e. std::unordered_map instead of plain integer variables. So it's possible to access values by their names, as strings.
Please consider the following code:
#include <string>
#include <iostream>
#include <unordered_map>
using namespace std;
class Character {
public:
void setAttr(const string& Sname, int Shealth, int SattackLevel, int SdefenseLevel) {
name = Sname;
values.insert(std::make_pair("health", Shealth));
values.insert(std::make_pair("attackLevel", SattackLevel));
values.insert(std::make_pair("defenseLevel", SdefenseLevel));
}
int outputInt(const string& whatToOutput) {
return values.at(whatToOutput);
}
private:
string name;
std::unordered_map<std::string, int> values;
};
int main(int argc, char* argv[]) {
Character yourCharacter;
yourCharacter.setAttr("yourName", 10, 100, 1000);
std::cout << "Health: " << yourCharacter.outputInt("health") <<std::endl;
std::cout << "Attack level: " << yourCharacter.outputInt("attackLevel") << std::endl;
std::cout << "Defense level: " << yourCharacter.outputInt("defenseLevel") << std::endl;
return 0;
}
It will output as expected:
Health: 10
Attack level: 100
Defense level: 1000
Another option without dependency on unordered_map would be, to use predefined static strings for your variable names and an array or vector for your values. So we could replace the class Character above with something like:
static std::string variableNames[3] = {
"health",
"attackLevel",
"defenseLevel"
};
class Character {
public:
void setAttr(const string& Sname, int Shealth, int SattackLevel, int SdefenseLevel) {
name = Sname;
variableValues[0] = Shealth;
variableValues[1] = SattackLevel;
variableValues[2] = SdefenseLevel;
}
int outputInt(const string& whatToOutput) {
int retVal = 0;
for (size_t i = 0; i < sizeof(variableNames)/sizeof(std::string); ++i) {
if (!whatToOutput.compare(variableNames[i])) {
retVal = variableValues[i];
}
}
return retVal;
}
private:
string name;
int variableValues[3];
};
And getting still same output. However, here you have to manage a list with all your variable names inside the string array manually - I don't like this solution and would prefer one of the others above personally.
Most common ways in C++ to handle such a design is to have seperate getHealth(), getAttackLevel(), getDefenseLevel() functions instead. However, this will miss one use-case, which is: if you want to let the user input a string, like i.e. "health" and display the corresponding variable then, you would need to write code by yourself to call the corresponding getXXX() function. If this is not a issue in your case, consider the following code which is much cleaner:
#include <string>
#include <iostream>
using namespace std;
class Character {
public:
void setAttr(const string& Sname, int Shealth, int SattackLevel, int SdefenseLevel) {
name = Sname;
health = Shealth;
attackLevel = SattackLevel;
defenseLevel = SdefenseLevel;
}
int getHealth() const { return health; }
int getAttackLevel() const { return attackLevel; }
int getDefenseLevel() const { return defenseLevel; }
private:
string name;
int health, attackLevel, defenseLevel;
};
int main(int argc, char* argv[]) {
Character yourCharacter;
yourCharacter.setAttr("yourName", 10, 100, 1000);
std::cout << "Health: " << yourCharacter.getHealth() <<std::endl;
std::cout << "Attack level: " << yourCharacter.getAttackLevel() << std::endl;
std::cout << "Defense level: " << yourCharacter.getDefenseLevel() << std::endl;
return 0;
}
One other unrelated advice: Instead of using string as parameter types for your functions, use const string& (const reference to string; see my example code above). This allows easier calling of your functions (they can be called directly with an string literal without the need to create additional variables in the calling code) and they will not make a additional unnecessary copy. The only copy then will take place at: name = Sname; (in your code two copies took place).
I don't know if it can be a good idea for you, but you can use a public typedef struct that you pass by reference and set your value.
class Character {
public:
//...
typedef struct allvalues{
string vname;
int vhealth;
int vattackLevel;
int vdefenseLevel;
}allvalues;
void getValues(allvalues& val){
val.vname = name;
val.vhealth = health;
val.vattackLevel = attackLevel;
val.vdefenseLevel = detenseLevel;
}
//...
};
//...
//somewhere in the code
Character myCarac;
//...
//Here how to use it
Character::allvalues values;
myCarac.getValues(values);

scope error message

Hey guys, just learning about composition of classes and ran into this error.
Gradebook.h
#ifndef GRADEBOOK_h
#define GRADEBOOK_h
#include "StudentRec.h"
#include <iostream>
#include <string>
class GradeBook
{
public:
GradeBook();
GradeBook(string initLastName, int studGrades);
void AddStudent(string initLastName, int studGrades);
void ShowStudents();
void UserInterface();
private:
static const int numStudents=20;
StudentRec student[numStudents];
static int studentCounter;
static int gradeCounter;
};
#endif
Gradebook.cpp
#include "Gradebook.h"
#include "StudentRec.h"
#include <iostream>
#include <string>
using namespace std;
GradeBook::GradeBook()
{}
GradeBook::GradeBook(string initLastName, int studGrades)
{}
void GradeBook::AddStudent(string initLastName, int studGrades)
{
gradeCounter++; //Increments variable responsible for tracking # of grades per student
StudentRec newStudent(initLastName, studGrades); //creates new student object
student[studentCounter]=newStudent; //Assigns new student object to array
studentCounter++; //Increments variable responsible for tracking # of students
}
void GradeBook::ShowStudents()
{
for(int i=0;i<studentCounter; i++){ //Displays information for each student instance
cout<<student[i].GetLastName()<<' ';
for(int j=0; j<gradeCounter; j++)
cout<<student[i].GetGrades(j)<<' ';
cout<<endl;
}
}
void GradeBook::UserInterface()
{
char choice=' ';
string studLastName;
int studGrade;
cout<<"Welcome to GradeBook, this program stores students"
<<" grades by last name. To ADD a student press the 'A'"
<<" key. To LIST all students, press the 'L' key. To "
<<" QUIT, press the 'Q' key."<<endl<<endl;
cin>>choice;
choice=toupper(choice);
while(choice!='Q')
{
if(choice='A'){
cout<<"To add a student, please enter their last name"
<<" followed by a space and a non-negative grade"
<<" Ex. McClure 96";
cin>>studLastName>>studGrade;
AddStudent(studLastName, studGrade);
}
else if(choice='L'){
cout<<"This is a list of all students in GradeBook"
<<endl<<endl;
ShowStudents(); //Displays all StudentRec objects
}
else if(choice!='Q')
cout<<"Please enter another letter"<<endl;
cout<<"To ADD a student press the 'A' key. To LIST all students, press the 'L' key. To "
<<" QUIT, press the 'Q' key."<<endl<<endl;
}
}
Main.cpp
#include <iostream>
#include <string>
#include "StudentRec.h"
#include "Gradebook.h"
using namespace std;
int main()
{
GradeBook gradeBook;
UserInterface();
return 0;
}
StudentRec.cpp
#include <iostream>
#include <string>
#include "StudentRec.h"
using namespace std;
StudentRec::StudentRec()
{
lastName=" ";
for(int i=0;i<numGrades; i++)
grades[i]=0;
}
StudentRec::StudentRec(string initLastName, int studGrade)
{
static int gradeCounter=0;
lastName=initLastName;
grades[gradeCounter]=studGrade;
}
string StudentRec::GetLastName()
{
return lastName;
}
int StudentRec::GetGrades(int gradeNum)
{
return grades[gradeNum];
}
void StudentRec::AddGrades(int studGrade)
{
gradeCounter++;
if(gradeCounter<=numGrades)
grades[gradeCounter]=studGrade;
else
cout<<"Too many grades for this student";
}
StudentRec.h
#ifndef STUDENTREC_h
#define STUDENTREC_h
#include <iostream>
#include <string>
using namespace std;
class StudentRec
{
public:
StudentRec();
StudentRec(string initLastName, int studGrade);
string GetLastName();
int GetGrades(int gradeNum);
void AddGrades(int studGrade);
private:
static const int numGrades=10;
static int gradeCounter;
string lastName;
int grades[numGrades];
};
#endif
In the Main.cpp file, I get an error I can't find the solution for. It reads
error: "UserInterface" was not declared in this scope. I got this error while compiling in XCode
I got error C3861: 'UserInterface': identifier not found
Obviously i've tried it in two IDEs, I also have the StudentRec.cpp and .h, but not sure you need them. Thanks in advance for the help
It appears that UserInterface() is actually a member function of GradeBook, correct?
If so, you need to add a declaration for the member function in the GradeBook class declaration:
class GradeBook
{
public:
GradeBook();
GradeBook(string initLastName, int studGrades);
void AddStudent(string initLastName, int studGrades);
void ShowStudents();
void UserInterface(); // Added
// ...
private:
// ...
};
This way, the compiler will "know" that the UserInterface() function exists as a member function. You then provided the definition in void GradeBook::UserInterface() in your .cpp file.
Then you need to call it on a GradeBook instance, like the gradeBook variable in your main() function:
int main()
{
GradeBook gradeBook;
// This calls the member function UserInterface() on the gradeBook variable.
gradeBook.UserInterface();
// This calls the global UserInterface(), which doesn't exist.
// UserInterface();
return 0;
}
UserInterface() is a method of GradeBook. The call probably needs to be:
gradeBook.UserInterface();