I'm new to C++ and stuck on a problem. I want class Admin to be able to create new objects of the Student class and add the objects to an array that contains all students' info. How can I do that in the Admin class?
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
class Student
{
public:
int SSN_LENGTH = 9, MIN_NAME_LEN = 1, MAX_NAME_LEN = 40;
string DEFAULT_NAME = "no name", DEFAULT_SSN = "000000000";
private:
string studentName, SSN;
public:
// constructor declarations
Student();
Student( string studentName, string SSN);
// Accessors
string getSSN(){ return SSN; }
string getStudentName(){ return studentName; }
// Mutators
bool setSSN(string SSN);
bool setStudentName(string studentName);
};
class Admin
{
private:
static const int Student_MAX_SIZE = 100000;
public:
bool addStudent (string studentName, string SSN);
};
How can I do that in the Admin class?
Use std::vector, illustrated by the code below:
#include <vector>
//...
class Admin
{
private:
static const std::size_t Student_MAX_SIZE = 100000;
std::vector<Student> vStudent;
public:
bool addStudent (string studentName, string SSN)
{
if ( vStudent.size() < Student_MAX_SIZE )
{
vStudent.push_back(Student(studentName, SSN));
return true;
}
return false;
}
};
Related
I need to get in a vector the names of some cities as soon as they are created... In order to accomplish that I created a static vector for the class City, however when I try to compile my code I get the error
error: lvalue required as unary '&' operand
this->cities.push_back(&this);
^~~~
What am I doing wrong?
My code is the following...
#include <iostream>
#include <ctime>
#include <vector>
using namespace std;
class City
{
private:
string name;
static vector<City *> cities;
public:
string getName() { return name; }
City(string name) : name{name}
{
this->cities.push_back(&this);
};
~City(){};
} hongKong{"Hong Kong"}, bangkok{"Bangkok"}, macau{"Macau"}, singapura{"Singapura"}, londres{"Londres"}, paris{"Paris"}, dubai{"Dubai"}, delhi{"Delhi"}, istambul{"Istambul"}, kuala{"Kuala"}, lumpur{"Lumpur"}, novaIorque{"Nova Iorque"}, antalya{"Antalya"}, mumbai{"Mumbai"}, shenzen{"Shenzen"}, phuket{"Phuket"};
int main()
{
}
this is already a City* pointer, so drop the & from &this.
Also, don't forget to actually define the static vector object.
Also, you should account for the class' copy/move constructors and destructor, to make sure you don't miss adding pointers, or leave behind dangling pointers.
Try this:
#include <iostream>
#include <ctime>
#include <vector>
using namespace std;
class City
{
private:
string name;
static vector<City *> cities;
public:
string getName() { return name; }
City(string name) : name{name}
{
cities.push_back(this);
}
City(const City &src) : name{src.name}
{
cities.push_back(this);
}
City(City &&src) : name{std::move(src.name)}
{
cities.push_back(this);
}
~City()
{
cities.erase(std::find(cities.begin(), cities.end(), this));
}
};
vector<City *> City::cities;
City hongKong{"Hong Kong"}, bangkok{"Bangkok"}, macau{"Macau"}, singapura{"Singapura"}, londres{"Londres"}, paris{"Paris"}, dubai{"Dubai"}, delhi{"Delhi"}, istambul{"Istambul"}, kuala{"Kuala"}, lumpur{"Lumpur"}, novaIorque{"Nova Iorque"}, antalya{"Antalya"}, mumbai{"Mumbai"}, shenzen{"Shenzen"}, phuket{"Phuket"};
int main()
{
}
I am relatively new to c++ and I have just learned how to use an array in a class, but I can't figure out how to add private members of one class to an array of a different class. I have a base class named collection, and a derived class called wallHangingType. When I try to input the length and width variable from wallHangingType into the array I get the error class collection has no member named 'length' or 'width'. I am required to have length and width in wallHangingType and not move them to the collection class. I would like to know how I would fix this to be able to input the length and width variables into the array.
collection.h
#ifndef COLLECTION_H
#define COLLECTION_H
#include <string>
class collection
{
public:
collection(int = 0, std::string = "NA", std::string = "NA");
std::string getArtistName();
std::string getTitle();
void setTitle(std::string artTitle);
void setArtist(std::string artist);
void setId(int id);
void print() const;
private:
std::string artistName;
std::string title;
int idNum;
};
#endif // COLLECTION_H
wallHangingType.h
#ifndef WALLHANGINGTYPE_H
#define WALLHANGINGTYPE_H
#include "collection.h"
class wallHangingType:public collection
{
public:
wallHangingType();
void addPiece(int id, std::string name, std::string artTitle,int artLength, int artWidth);
void removePiece();
void printArt();
private:
int length;
int width;
collection pieces[100];
int index;
};
#endif // WALLHANGINGTYPE_H
wallHangingType.cpp
#include <iostream>
using namespace std;
wallHangingType::wallHangingType()
{
index = 0;
}
void wallHangingType::addPiece(int id, std::string name, std::string artTitle,int artLength, int artWidth)
{
pieces[index].setId(id);
pieces[index].setArtist(name);
pieces[index].setTitle(artTitle);
pieces[index].length = artLength; //ERROR
pieces[index].width = artWidth; //ERROR
}
Here is my base class:
#include <string>
#include "DataStruct.h"
#include <vector>
#include <mysqlx/xdevapi.h>
#include <iostream>
#include <memory>
namespace Vibranium {
using namespace mysqlx;
class MySQLTable {
public:
MySQLTable();
virtual ~MySQLTable() = default;
int Index;
std::string tableName;
DataStruct dataStruct;
std::vector<std::unique_ptr<DataStruct>> Data;
Table getTable(Session& conn) const;
RowResult getAll(Session& conn) const;
virtual void LoadTable(RowResult& res) {}
};
}
#endif //VIBRANIUM_CORE_MYSQLTABLE_H
Which is representing all MySQL tables i might have. Take a look at Data vector of types DataStruct. I use DataStruct as a base struct because all tables will have different structure.
Here is base DataStruct struct:
namespace Vibranium{
struct DataStruct{};
}
Than I define my first mysql tablle Accounts:
#include <string>
#include "Database/DataStruct.h"
#include "Database/MySQLTable.h"
namespace Vibranium{
using namespace std;
struct AccountsStruct : DataStruct{
int id;
std::string email;
std::string warTag;
int state;
std::string name;
std::string lastname;
std::string country;
int dob_month;
int dob_day;
int dob_year;
double balance;
std::string created_at;
std::string updated_at;
int account_role;
int rank;
int playerRole;
};
class Accounts : public MySQLTable{
public:
Accounts() = default;
void LoadTable(RowResult& res) override;
};
}
As you can see inside I have defined AccountsStruct as child of DataStruct.
Here is how I implement LoadTable:
#include "Accounts.h"
using namespace Vibranium;
void Vibranium::Accounts::LoadTable(RowResult &res) {
std::vector<AccountsStruct> accounts;
AccountsStruct accountsStruct;
for (Row row : res.fetchAll()){
accountsStruct.id = row[0].get<int>();
accountsStruct.email = row[1].get<std::string>();
accountsStruct.warTag = row[2].get<std::string>();
accountsStruct.state = row[4].get<int>();
accountsStruct.name = row[5].get<std::string>();
accountsStruct.lastname = row[6].get<std::string>();
accountsStruct.country = row[7].get<std::string>();
accountsStruct.dob_month = row[8].get<int>();
accountsStruct.dob_day = row[9].get<int>();
accountsStruct.dob_year = row[10].get<int>();
accountsStruct.balance = row[11].get<double>();
accountsStruct.created_at = row[12].get<std::string>();
accountsStruct.updated_at = row[13].get<std::string>();
accountsStruct.account_role = row[15].get<int>();
accountsStruct.rank = row[16].get<int>();
accountsStruct.playerRole = row[17].get<int>();
accounts.push_back(accountsStruct);
}
}
As Accounts is child of MySQLTable
I would like to add all the data from std::vector<AccountsStruct> accounts into Data vector inherited from MySQlTable.
Also after that I would like to cycle thru the vector Data as it
is of type Accounts instead of MySQLTable class. However I don't
know how can I achieve those two things.
Is it possible and how?
I would drop the type DataStruct, and make MySqlTable a template.
#include <string>
#include <vector>
#include <mysqlx/xdevapi.h>
#include <memory>
namespace Vibranium {
using mysqlx::Table;
using mysqlx::RowResult;
using mysqlx::Session;
class MySQLTableBase {
public:
MySQLTableBase();
virtual ~MySQLTableBase() = default;
Table getTable(Session& conn) const;
RowResult getAll(Session& conn) const;
int Index;
std::string tableName;
};
template <typename T>
class MySQLTable : public MySQLTableBase {
public:
virtual void LoadTable(RowResult& res) = 0;
T dataStruct; // What is this?
std::vector<T> Data; // You don't need vector of pointers
};
}
Then you define Account and Accounts as
#include <string>
#include "Database/MySQLTable.h"
namespace Vibranium{
struct Account{
int id;
std::string email;
std::string warTag;
int state;
std::string name;
std::string lastname;
std::string country;
int dob_month;
int dob_day;
int dob_year;
double balance;
std::string created_at;
std::string updated_at;
int account_role;
int rank;
int playerRole;
};
class Accounts : public MySQLTable<Account>{
public:
Accounts() = default;
void LoadTable(RowResult& res) override;
};
}
So, have fun with C++!
You don't have a vector in MySQLTable with name "Data". You have method (Data) returning vector of ... To implement your request you should create method (for example) void SetData(...).
You can't. You can cycle through vector of Data and cast (for example static_cast, or other) each element from Data to AccountStruct. WARNING! Wrong cast operation may cause undefined behavior, crashes, etc.!
I have 2 classes. Since Doctor will be considered as Employee, I should be using Employee class functions in Doctor class. Only extra thing that Doctor class has is TITLE. Basically, What I tried is I wanted to send value to Doctor's constructor,set title then send remained value to Employee's class ;however, I could not. This is what I have done so far,
employee.h
#ifndef EMPLOYEE_H
#define EMPLOYEE_H
class Employee {
private:
int ID;
char *firstname;
char *lastname;
int telno;
char *adress;
char *mail;
int salary;
public:
Employee();
Employee(int,char *,char*,int,char*,char*,int);
char* getfmame();
char* getlname();
char* getadress();
char* getmail();
int getID();
int gettel();
int getsalary();
void printall();
};
#endif
Employee.cpp
#include <iostream>
#include "employee.h"
using namespace std;
Employee::Employee() {
firstname = "Empty";
ID=0;
firstname="Empty";
lastname="Empty";
telno=0;
adress="Empty";
mail="Empty";
salary=0;
}
Employee::Employee(int id,char * first,char* last,int tell,char* adres,char* email,int salar){
ID=id;
firstname=first;
lastname=last;
telno=tell;
adress=adres;
mail=email;
salary=salar;
}
char* Employee::getfmame(){ return firstname; }
char* Employee::getlname(){ return lastname; }
char* Employee::getadress(){ return adress; }
char* Employee::getmail(){ return mail; }
int Employee::getID(){ return ID; }
int Employee::gettel(){ return telno; }
int Employee::getsalary(){ return salary; }
void Employee::printall(){
cout<<endl<<"EMLOYEE INFORMATION"<<endl<<"------------------"<<endl;
cout<<endl<<"ID :"<<ID<<endl<<"FIRST NAME: "<< firstname <<endl<<"LAST NAME: "<< lastname << endl << "TELEPHONE NUMBER: "<<telno<<endl<<"ADRESS: "<<adress<<endl<<"MAIL: "<<mail<<endl<<"SALARY: "<<salary<<endl;
}
Doctor.h
#ifndef DOCTOR_H
#define DOCTOR_H
#include "Employee.h"
using namespace std;
class Doctor :Employee {
public:
enum title {Intern=0,Practitioner=1,Assistant=2,Specialist=3,Docent=4,Professor=5,None=6};
Doctor();
Doctor(title a,int id,char * first,char* last,int tell,char* adres,char* email,int salar);
};
#endif
Doctor.cpp
#include <iostream>
#include "Doctor.h"
#include "Employee.h"
using namespace std;
Doctor::Doctor() {
title tit = None ;
}
Doctor::Doctor(title a,int id,char * first,char* last,int tell,char* adres,char* email,int salar) {
title tit=a;
Employee(id,first,last, tell,adres,email,salar);
printall();
cout<<"typed";
}
Main.cpp
#include <iostream>
#include "employee.h"
#include "doctor.h"
using namespace std;
int main(){
Doctor a=Doctor(Doctor::None,12,"a","b",0550550505,"8424 str nu:5","#hotmail",5000);
return 0;
}
Subclass construction in C++ works so that the base class object must be constructed when the subclass' constructor body is executed:
class A {
/* etc. etc. */
public:
void do_stuff();
};
class B : public A {
B() {
// at this point, an A has already been constructed!
A::do_stuff();
}
};
Note that in this example, since we haven't chosen an explicit constructor for the A instance, the default constructor, A::A(), will be used; and if that constructor is unavailable - we get a compilation error. The fact that a constructor for A has been called is what allows us to then use methods of class A - like A::do_stuff() in the example above.
But - how can we specify a different constructor before the body of the B constructor? Or in your case, how can we use the appropriate constructor for Employee before the body of the Doctor constructor?
The answer was suggested by #user4581301: You need to use an member initializer list. Initializations/constructions on this list are performed before the body, and may include the underlying class. I'll demonstrate with a simplified example. Let's suppose an Employee only has an id and a Doctor only has an additional title.
class Employee {
protected:
int id_;
public:
Employee(int id) : id_(id) { };
int id() const { return id_; }
};
class Doctor : public Employee {
protected:
std::string title_;
public:
Doctor(int id, std::string title) : Employee(id), title_(title) { };
const std::string& title() const { return title_; }
};
So, when a Doctor is being constructed, it constructs its underlying Employee instance using the id it got. The constructor body is used for more complex code beyond simple member initializations.
PS:
You might want to initialize the title_ member with std::move(title) rather than just title, see this question for details.
It's confusing when a constructor has more than two or three parameters with compatible types - users are likely to confuse them with each other. You might consider default values for most fields and setting them after construction, or alternatively, using a builder pattern.
address, with two d's, not adress.
Unless you plan on editing char* fields in-place, use const char *.
They way you've written your classes, Doctor methods would not have write acesss to Employee methods; make sure that's what you intended.
I have some other nitpicks but I'll stop now...
For my homework I have to do a class Game in C++ that has name, size, and a list of updates that contain date of update and some information about that update. (for example : 22.05.2018 Bug fixed at quest 3). Here is what i tried, but it doesn't work. Game.h:
class Game{
public:
struct update{
string date;
string info;
};
string name;
double size;
list<update>l;
Game(string name, double size, list<update>l);
virtual ~Game();
};
and in Game.cpp:
Game::Game(string name, double size, list<update>l){
this->name=name;
this->size=size;
this->l=l;
}
In int main I created a list:
int main()
{
list<update>mylist;
update u1,u2,u3;
u1.date="20.05.2018";
u1.info="Mission 3 bug fixed";
u2.date="25.05.2018";
u2.info="New quest";
mylist.push_back(u1);
mylist.push_back(u2);
Game g("Gta5",60.0,mylist);
return 0;
}
i get this error:
no matching function for call to 'Game::Game(const char [4], double, std::__cxx11::list<update>&)'|
Or if you want to keep the nested class update:
#include <string>
#include <list>
using std::string;
using std::list;
class Game{
public:
struct update{
string date;
string info;
};
string name;
double size;
list<update>l;
Game(string name, double size, list<update>l);
virtual ~Game() {}
};
Game::Game(string name, double size, list<update>l){
this->name=name;
this->size=size;
this->l=l;
}
int main()
{
list<Game::update> mylist; // use Game::update to access nested class
Game::update u1,u2,u3;
u1.date="20.05.2018";
u1.info="Mission 3 bug fixed";
u2.date="25.05.2018";
u2.info="New quest";
mylist.push_back(u1);
mylist.push_back(u2);
Game g("Gta5",60.0,mylist);
return 0;
}
Try this,
#include<bits/stdc++.h>
using namespace std;
struct update
{
string date;
string info;
update(string date,string info){
this->date=date;
this->info=info;
}
};
class Game{
public:
string name;
double size;
list<update>l;
Game(string name, double size, list<update>l);
// virtual ~Game();
};
Game::Game(string name, double size, list<update>l){
this->name=name;
this->size=size;
this->l=l;
}
int main(){
list<update> l,m;
l.push_front(update("10/10/2017","some bug fixed"));
double size=100;
string name="Game1";
Game obj(name,size,l);
cout<<obj.name<<" "<<obj.size<<" "<<endl;
m=obj.l;
list<update>::iterator i;
for(i=m.begin();i!=m.end();i++){
update structObj=*i;
cout<<structObj.date<<" "<<structObj.info<<endl;
}
return 0;
}
Output
Game1 100
10/10/2017 some bug fixed