Changing scope from member to global function - c++

I'm attempting to change a print function from a member to a global function without modifying the main function. I am unable to compile this without modifying the main function, though.
class Student
{
char* name;
long ssn;
public:
Student (char*, long);
//void print();
char * getName ( );
long getSsn ( );
};
Student::Student(char* temp_name, long temp_ssn)
{
name = new char[strlen(temp_name) +1];
strcpy(name,temp_name);
ssn = temp_ssn;
}
char * Student::getName()
{
return name;
}
long Student::getSsn()
{
return ssn;
}
void print()
{
cout << "Name: " << getName() << endl;
cout << "SSN: " << getSsn() << endl;
}
int main ( )
{
Student S1("Mike", 222222222L);
S1.print();
return 0;
}
In particular, I was wondering if it is necessary to include void print(); in the public: section of the Student class? Or would that make it a member function?
Is it actually possible to do this without modifying the main function?
How do I access the class from a global function? Am I going to go crazy? Thank you, everyone.

Here's how to make print a global function.
class Student
{
char* name;
long ssn;
public:
Student (char*, long);
char * getName ( );
long getSsn ( );
};
Student::Student(char* temp_name, long temp_ssn)
{
name = new char[strlen(temp_name) +1];
strcpy(name,temp_name);
ssn = temp_ssn;
}
char * Student::getName()
{
return name;
}
long Student::getSsn()
{
return ssn;
}
void print(Student& s)
{
cout << "Name: " << s.getName() << endl;
cout << "SSN: " << s.getSsn() << endl;
}
int main ( )
{
Student S1("Mike", 222222222L);
print(S1);
return 0;
}
Notice that I've added a Student& parameter to print, it has to know which student to print after all. And in main I've changed the way print is called so it has a Student parameter, instead of calling a method on Student.
I'm sure the point of the exercise is to show that you can achieve the same effects using either global functions or member functions.

Related

.Can there be a easier function defining - (to.string()) below

// The function which i was required to make was to.string() in the class,Which i had no idea how to make.This is an odd function(not comparing with the math one.)which returns value in two different types of data types i.e(string,integer).The only thing stuck me was assigning a variable after making (string to.string()) function//The return value of function is something like
[age,first_name,last_name,standard](without the square brackets with the commmasin the output)
p.s=need a simpler function without using vector header.
#include <iostream>
#include <sstream>
using namespace std;
class Student{
public :
void set_age(int no){
age_no=no;
}
void set_standard(int no){
std_no=no;
}
void set_first_name(string identity){
name_letter=identity;
}
void set_last_name(string identity2){
last_name_letter = identity2;
}
int get_age(){
return age_num;
}
int get_standard(){
return std_no;
}
string get_first_name(){
return name_letter;
}
string get_last_name(){
return last_name_letter;
}
private :
int age_no;
int std_no;
string name_letter;
string last_name_letter;
};
int main() {
int age, standard;
string first_name, last_name;
cin >> age >> first_name >> last_name >> standard;
Student st;
st.set_age(age);
st.set_standard(standard);
st.set_first_name(first_name);
st.set_last_name(last_name);
cout << st.get_age() << "\n";
cout << st.get_last_name() << ", " << st.get_first_name() << "\n";
cout << st.get_standard() << "\n";
cout << "\n";
cout << st.to_string();
return 0;
}
If you want to create a string with the format age, first_name, last_name, standard then you could do something like
class Student
{
public:
...
std::string to_string() const;
...
};
std::string Student::to_string() const
{
return std::to_string(get_age()) + ", " +
get_first_name() + ", "
get_last_name() + ", "
std::to_string(get_standard());
}
As an aside, I would suggest making all of your getter functions const for example
int get_age() const;
This denotes that the method will not mutate or modify any of the values of the class's member variables.

Is it possible to use same functions for every class

I have multiple classes and each of them has their own methods. All of these methods perform the same task, as you can see in my code. The only unique thing is the values of the title, code and credit members that are defined inside the classes.
Is there a way to write this code such that a single set of methods can do the required tasks (using the specific values within the class that made the request to the method) for each and every class?
I'm a university student, and due to this I don't want to use inheritance since we haven't learned it yet.
class seng305
{
string title = "Software design and architecture", code = "SENG305";
int credit = 4;
public:
seng305();
~seng305();
string get_info();
string get_title();
int get_credit();
};
class comp219
{
string title = "Electronics in computer engineering", code = "COMP219";
int credit = 4;
public:
comp219();
~comp219();
string get_info();
string get_title();
int get_credit();
};
seng305::seng305()
{
cout << '\t' << "Created" << endl;
}
seng305::~seng305()
{
cout << '\t' << "Destroyed" << endl;
}
string seng305::get_info()
{
return (code + "-" + title);
}
string seng305::get_title()
{
return title;
}
int seng305::get_credit()
{
return credit;
}
//--------------------------------------------------
comp219::comp219()
{
cout << '\t' << "Created" << endl;
}
comp219::~comp219()
{
cout << '\t' << "Destroyed" << endl;
}
string comp219::get_info()
{
return (code + "-" + title);
}
string comp219::get_title()
{
return title;
}
int comp219::get_credit()
{
return credit;
}
As you can see, the get_info(), get_title(), and get_credit() methods do the same thing.
I would like for a single get_info(), get_title(), get_credit() to be able to do the task for each class.
There is no reason to use separate classes at all in this example. A single class will suffice, eg:
class course
{
string title, code;
int credit;
public:
course(const string &title, const string &code, int credit);
~course();
string get_info() const;
string get_title() const;
int get_credit() const;
};
course::course(const string &title, const string &code, int credit)
: title(title), code(code), credit(credit)
{
cout << '\t' << "Created" << endl;
}
course::~course()
{
cout << '\t' << "Destroyed" << endl;
}
string course::get_info() const
{
return (code + "-" + title);
}
string course::get_title() const
{
return title;
}
int course::get_credit() const
{
return credit;
}
Then, you simply create instances of your class as needed, eg:
course seng305("Software design and architecture", "SENG305", 4);
course comp219("Electronics in computer engineering", "COMP219", 4);
...
I know you said that you don't want to use inheritance, but that could be the next logical step, using the above code as a base:
class courseSeng305 : public course
{
public:
courseSeng305() : course("Software design and architecture", "SENG305", 4) {}
};
class courseComp219 : public course
{
public:
courseComp219() : course("Electronics in computer engineering", "COMP219", 4) {}
};
courseSeng305 seng305;
courseComp219 comp219;
...

C++: Derived classes, "no matching constructor" error

I've been working on this assignment for a while. Here's the instructions:
You are to design an abstract class called Employee whose members are
as given below (make them protected):
Data members: char *name, long int ID
Two constructors: A Default constructor // intitialize data memebrs to
the default values and a copy constructor
Methods: setPerson (char *n, long int id) //allows user to set
information for each person A function called Print () // should be a
virtual function, that prints the data attributes of the class. and a
destructor
Also define two classes that derived from class Employee, called
Manager and Secretary. Each class should inherit all members from the
base class and has its own data members and member functions as well.
The Manager should have a data member called degree for his/her
undergraduate degree (e.g. diploma, bachelor, master, doctor), the
Secretary should have her contract (can be a Boolean value 1/0 for
permanent/temporary).
All member functions of derived class should be overrided from their
base class.
Write the following main() to test your classes
int main() {
Employee * p = new Manager(“Bruce Lee”, 0234567, “Dr.”);
P.print();
Secretary p2;
p2.setPerson(“Wilma Jones”, 0341256, “permanent”);
delete p;
p = & p2;
p.Print();
return 0;
}
This is everything I've come up with so far, but I'm pretty sure it's riddled with mistakes and that my arguments and variable types are all off.
#include <iostream>
using namespace std;
class Employee{
protected:
char *name;
long int ID;
public:
Employee();
Employee(Employee&);
void setPerson(char * n, long int eID) {
name = n;
ID = eID; };
virtual void Print(){
cout << "Name: " << name << endl;
cout << "ID: " << ID << endl; };
};
class Manager: public Employee {
protected:
char *degree;
public:
void setPerson(char * n, long int eID, char * d){
name = n;
ID = eID;
degree = d;
};
void Print() {
cout << "Name: " << name << endl;
cout << "ID: " << ID << endl;
cout << "Degree: " << degree << endl;
};
};
class Secretary: public Employee {
protected:
bool contract;
public:
void setPerson(char * n, long int eID, string c){
name = n;
ID = eID;
if (c == "permanent") contract = true;
else contract = false;
};
void Print(){
cout << "Name: " << name << endl;
cout << "ID: " << ID << endl;
cout << "Contract: " << contract << endl;
};
};
int main() {
Employee * P = new Manager("Bruce Lee", 0234567, "Dr.");
P.Print();
Secretary P2;
P2.setPerson("Wilma Jones", 0341256, "permanent");
delete P;
P = & P2;
P.Print();
return 0;
}
I'm getting an error on line 62 (the first line of the main code):
No matching constructor for initialization of Manager
I've tried reading similar questions, but they haven't helped me much. I think the most confusing thing is contract being a bool value and the use of char arguments. Any guidance at all is appreciated.
The error you're getting is pretty straight-forward: you don't have any constructor for Manager (or Employee) that takes a string, integer (?), and string as arguments.
You have declared the constructor employee but not defined it.
Look at the class employee, Under publc you have declared
Employee();
Employee(Employee&);
But you have not defined the function. You need
Employee :: Employee()
{
bla bla bla
}
and another one for the other signature.

How do you change the value of a single member of a struct pointer?

#include <iostream>
#include <cstring>
using namespace std;
struct Student {
int no;
char grade[14];
};
void set(struct Student* student);
void display(struct Student student);
int main( ) {
struct Student harry = {975, "ABC"};
set(&harry);
display(harry);
}
void set(struct Student* student){
struct Student jim = {306, "BBB"};
*student = jim; // this works
//*student.no = 306; // does not work
}
void display(struct Student student){
cout << "Grades for " << student.no;
cout << " : " << student.grade << endl;
}
How can I change just one member of the structure with a pointer? Why does *student.no = 306 not work? Just a bit confused.
If you have a pointer to a struct, you should use -> to access it's members:
student->no = 306;
This is syntactic sugar for doing (*student).no = 306;. The reason yours didn't work is because of operator precedence. Without the parentheses, the . has higher precedence than *, and your code was equivalent to *(student.no) = 306;.
operator* has very low precedence, so you have to control the evaluation with parenthesis:
(*student).no = 306;
Though it can always be done as:
student->no = 306;
which in my opinion is much easier.
You should use
student->no = 36
While we are at it, it is not a good practice to pass structs by value to functions.
// Use typedef it saves you from writing struct everywhere.
typedef struct {
int no;
// use const char* insted of an array here.
const char* grade;
} Student;
void set(Student* student);
void display(Student* student);
int main( ) {
// Allocate dynmaic.
Student *harry = new Student;
harry->no = 957;
harry->grade = "ABC";
set(harry);
display(harry);
}
void set(Student *student){
student->no = 306;
}
void display(Student *student){
cout << "Grades for " << student->no;
cout << " : " << student->grade << endl;
delete student;
}

How should I define an abstract method in the base class when descendants need different parameter lists?

Here is my code:
class LibItem
{
public:
virtual void PrintDetails() = 0;
virtual void setDetails() = 0;
void setTitle(string TitleName)
{
Title = TitleName;
}
string getTitle()
{
return Title;
}
void setReleaseDate(string date)
{
ReleaseDate = date;
}
string getReleaseDate()
{
return ReleaseDate;
}
void setAuthor(string AuthorName)
{
Author = AuthorName;
}
string getAuthor()
{
return Author;
}
void setCopyright(string CopyrightDetails)
{
Copyright = CopyrightDetails;
}
string getCopyright()
{
return Copyright;
}
void setGenre(string GenreDetails)
{
Genre = GenreDetails;
}
string getGenre()
{
return Genre;
}
void setStatus(string StatusDetails)
{
Status = StatusDetails;
}
string getStatus()
{
return Status;
}
private:
string Title;
string ReleaseDate;
string Author;
string Copyright;
string Genre;
string Status;
};
class Book : public LibItem
{
public:
Book(string TitleName)
{
setTitle(TitleName);
}
void setISBN(int ISBNDetails)
{
ISBN = ISBNDetails;
}
int getISBN()
{
return ISBN;
}
void setDetails(string setBookTitle, string setBookAuthor, string setBookReleaseDate, string setBookCopyright, string setBookGenre, string setBookStatus, int setBookISBN)
{
setTitle(setBookTitle);
setAuthor(setBookAuthor);
setReleaseDate(setBookReleaseDate);
setCopyright(setBookCopyright);
setGenre(setBookGenre);
setStatus(setBookStatus);
setISBN(setBookISBN);
}
void PrintDetails()
{
cout << "Title: " << getTitle() << endl;
cout << "Author: " << getAuthor() << endl;
cout << "Release Date: " << getReleaseDate() << endl;
cout << "Copyrite: " << getCopyright() << endl;
cout << "Genre: " << getGenre() << endl;
cout << "Status: " << getStatus() << endl;
cout << "ISBN: " << getISBN() << endl;
}
private:
Book();
int ISBN;
};
class DVD : public LibItem
{
public:
DVD(string TitleName)
{
setTitle(TitleName);
}
void setRunningTime(int RunningTimeDetails)
{
RunningTime = RunningTimeDetails;
}
int getRunningTime()
{
return RunningTime;
}
void setDirector(string DirectorDetails)
{
Director = DirectorDetails;
}
string getDirector()
{
return Director;
}
void setStudio(string StudioDetails)
{
Studio = StudioDetails;
}
string getStudio()
{
return Studio;
}
void setProducer(string ProducerDetails)
{
Producer = ProducerDetails;
}
string getProducer()
{
return Producer;
}
void setDetails(string setDVDTitle, string setDVDAuthor, string setDVDReleaseDate, string setDVDCopyright, string setDVDGenre, string setDVDStatus, int setDVDRunningTime, string setDVDDirector, string setDVDStudio, string setDVDProducer)
{
setTitle(setDVDTitle);
setAuthor(setDVDAuthor);
setReleaseDate(setDVDReleaseDate);
setCopyright(setDVDCopyright);
setGenre(setDVDGenre);
setStatus(setDVDStatus);
setDirector(setDVDDirector);
setStudio(setDVDStudio);
setProducer(setDVDProducer);
}
void PrintDetails()
{
cout << "Title: " << getTitle() << endl;
cout << "Author: " << getAuthor() << endl;
cout << "Release Date: " << getReleaseDate() << endl;
cout << "Copyrite: " << getCopyright() << endl;
cout << "Genre: " << getGenre() << endl;
cout << "Status: " << getStatus() << endl;
cout << "Running Time: " << getRunningTime() << endl;
cout << "Director: " << getDirector() << endl;
cout << "Studio: " << getStudio() << endl;
cout << "Producer: " << getProducer() << endl;
}
private:
DVD();
int RunningTime;
string Director;
string Studio;
string Producer;
};
I am having trouble with the virtual void setDetails();
I am wanting both the Book and DVD class to have a method called setDetails to set the details. The problem is, both the Book class and the DVD class have different arguments for this method.
How can I achieve this?
How is the best way to solve this problem?
Since
setDetails(string setDVDTitle, string setDVDAuthor, string setDVDReleaseDate, string setDVDCopyright, string setDVDGenre, string setDVDStatus, int setDVDRunningTime, string setDVDDirector, string setDVDStudio, string setDVDProducer)
only makes sense for a DVD object, and
setDetails(string setBookTitle, string setBookAuthor, string setBookReleaseDate, string setBookCopyright, string setBookGenre, string setBookStatus, int setBookISBN)
only makes sense for a Book, the methods shouldn't be virtual, nor in the base class.
Say I give you a LibItem* and I tell you to set its details. What do you do? Does it make sense to set its details, since they differ from one concrete implementing class to another?
The base class should only have the method that sets:
string Title;
string ReleaseDate;
string Author;
string Copyright;
string Genre;
string Status;
which shouldn't be virtual, since its behavior doesn't change from implementation to implementation, and you should set specific details on the implementing classes themselves.
The abstract base class can only contain functions that are common to all derived classes, so if you need different functions in different derived classes, they can't go in the base class.
You could downcast to get the derived type, and access its type-specific functions:
LibItem & item = some_item();
if (Book * book = dynamic_cast<Book*>(&item)) {
book->setDetails(book_details);
} else if (DVD * dvd = dynamic_cast<DVD*>(&item)) {
dvd->setDetails(dvd_details);
}
If you have many different types, and many type-specific operations, then it might be worth considering the Visitor pattern; but that's overkill in most situations.
you cant, you need common interface. http://www.tutorialspoint.com/cplusplus/cpp_interfaces.htm . This article will help you a lot in understanding of abstract classes. Member function which has different arguments for different childs shouldnt be virtual.
Looking into your code:
try to change your arguments type from "string" to "const string&" you will avoid copies.
virtual void LibItem::setDetails() = 0;
and
void Book::setDetails(string setBookTitle, string setBookAuthor, string setBookReleaseDate, string setBookCopyright, string setBookGenre, string setBookStatus, int setBookISBN)
and
void DVD::setDetails(string setDVDTitle, string setDVDAuthor, string setDVDReleaseDate, string setDVDCopyright, string setDVDGenre, string setDVDStatus, int setDVDRunningTime, string setDVDDirector, string setDVDStudio, string setDVDProducer)
are different methods, so, there is no overloading in your code.
BTW. Don't forget about virtual destructor in your LibItem...
There are two ways you could handle this. The first involves varargs,
declaring the interface in the base to be setDetails( std::string
const& title... ). I will not go further into this way, however, as it
is a sure path to unexplained crashes later down the road. The other
solution is to use something like: setDetails( std::map< std::string,
std::string > const& ), and in the concrete implementation extract the
details you want by name. Even then, I'm not sure it's a good solution,
since given a LibItem*, you don't know what to put in the map. (It
could be a valid solution if you get the type of object and the list
of details from the user. Even then, I'd probably encapsulate this into
a factory function, which would know the type it is creating, verify
that the details correspond, and then pass all of the details to the
constructor.)
And while I'm at it: you can't use an int for ISBN. The most reasonable representation is a string.