I keep getting the following errors from my code:
(line 58) error: no 'std::string Person::Modify_Person(Person)' member function declared in class 'Person' In function 'int main()':
(line 113) error: 'Modify_Person' was not declared in this scope
Here is the code:
#include <iostream>
#include <string>
using namespace std;
void PassByByValue(int num2){
cout << "You are in PassByValue()" << endl;
num2++;
}
class Person{
int age;
string name;
int height;
int weight;
public:
Person(){
}
Person(string name){
this->name=name;
}
string getName(){
return this->name;
}
void setAge(int age){
this->age=age;
}
void setName(string name){
this->name=name;
}
void setHeight(int height){
this->height=height;
}
void setWeight(int weight){
this->weight=weight;
}
~Person(){
}
};
string Person::Modify_Person(Person example){
example.getName()="Jessica";
return example.getName();
}
void PassByRef(int& num3){
cout << "You are in PassByRef()" << endl;
num3=50;
cout << "inside PassByRef() pNum is: " <<num3<<endl;
}
int main()
{
int num1;
int* pNum;
num1=3;
*pNum=5;
PassByByValue(num1);
cout << "num1= " <<num1 <<endl;
PassByRef(*pNum);
cout << "outside PassByRef() in main() pNum is: " <<pNum<<endl;
PassByByValue(*pNum);
double* DblePtr;
DblePtr= new double;
*DblePtr=12.0;
cout<< "DblePtr: "<< &DblePtr;
delete[] DblePtr;
cout<< "DblePtr: "<< &DblePtr;
Person human;
human.setName("Kate");
human.setAge(27);
human.setHeight(100);
human.setWeight(100);
Modify_Person(human);
cout << "Modify_Person returns: " << Modify_Person(human) <<endl;
cout << "name should be Jessica: " << human.getName() << endl;
return 0;
}
You cannot declare a member function outside a class in C++. To fix this, add a corresponding member function declaration to your class:
class Person{
...
public:
string Modify_Person(Person);
};
Then your code will work. Also, a suggestion: don't define constructors and destructors if they are empty; allow the compiler to generate them for you. If you are intending to disable move constructors etc. by doing this, write Person() = default; to have the compiler generate a default implementation.
The function
string Person::Modify_Person(Person example) {
example.getName()="Jessica";
return example.getName();
}
has the following problems.
Use of string Person::Modify_Person(Person example) { ... } to define a function is valid only of Modify_Person is declared as a member function of the class. Since, it is not, you just need a global function.
string Modify_Person(Person example) {
...
}
The function cannot modify the object in the calling functions since the argument gets passed by value. No matter what you do to example, the value of the object that was used to call the function remains unchanged in the calling function. If you want to see any changes made to example to be visible in the calling function, you need to accept the argument by reference.
// |
// v
string Modify_Person(Person& example) {
...
}
The line
example.getName()="Jessica";
in the function does not modify the name of example. It is equivalent to saying:
string temp = example.getName();
temp = "Jessica";
Hence, the line below that returns the name of example will simply return the name of example, and not "Jessica", which I believe is counter to your expectation.
That line needs to be changed to:
example.setName("Jessica");
Here's what the function should look like:
string Modify_Person(Person& example) {
example.setName("Jessica");
return example.getName();
}
Related
In c++, the changes done to the argument inside a function aren't reflected in the actual variable if
the return value of function is void, but that's not the case with the member functions where we can
see the changes happening permanently.
#include<iostream>
using namespace std;
class Student {
public:
int age;
float marks;
Student()
{
cout << "call by default";
}
void ageInc()
{
age = age + 1;
}
};
int main()
{
Student s;
s.age = 34;
cout << s.age << endl;
s.ageInc();
cout << s.age << endl;
return 0;
}
In c++, the changes done to the argument inside a function aren't reflected in the actual variable if the return value of function is void
Changes to an argument's value has nothing at all to do with a function's return type. A void function can quite easily make changes to its arguments. Whether or not those changes are reflected back to the caller has to do with whether the argument is passed by pointer/reference or not.
but that's not the case with the member functions where we can see the changes happening permanently.
A non-static class method receives a hidden this pointer to the object it is being called on. When the method accesses a non-static member of its owning class, it is using that this pointer to access the member. So any changes made to the member are done directly to the mmeber.
Your example is roughly equivalent to the following behind the scenes:
#include <iostream>
using namespace std;
struct Student {
int age;
float marks;
};
Student_ctr(Student* const this)
{
cout << "call by default";
}
Student_dtr(Student* const this) {}
void Student_ageInc(Student* const this)
{
this->age = this->age + 1;
}
int main()
{
Student s;
Student_ctr(&s);
s.age = 34;
cout << s.age << endl;
Student_ageInc(&s);
cout << s.age << endl;
Student_dtr(&s);
return 0;
}
Because you're not changing an argument. Your example function takes no arguments. You're changing a member variable.
You could think of all members of the object as being automatic passed-by-reference parameters, but this isn't how C++ encourages you to think of them.
I have a problem doing my homework. the problem I faced is this:
the question is this:
((write a program that prints the name of the human/employee with maximum sort_param.use template programming.))
human and employee are defined like this:
struct human
{
char name[30];
char * family;
int id;
int sort_param;
};
struct employee
{
human h;
char post[50];
int sort_param;
};
as you see, printing the name of the employee/human depends on the type that is passed to the function.
my question is:
how can I tell the computer to act depend on the data type. I mean if the type is employee then:
cout << employee.h.name << endl;
if the type is human then:
cout << human.name << endl;
use an overloaded function, just call your function with one of arguments those type can be human or employee.
void print_name(const employee& emp)
{
cout << emp.h.name << endl;
}
void print_name(const human& hum)
{
cout << hum.name << endl;
}
The argument are edited.
I'm working on an inheritance assignment and wanted to firstly test out my base class with its setters, getters, and constructors, but I'm already hitting a wall.
What's wrong with my constructor? I would normally just use a no argument constructor and use the setters and getters to build the object, but we're specifically told to use both types of constructors. Can someone help me out?
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <string>
using namespace std;
class Ship
{
public:
Ship();
Ship(string theName, int theYear);
string getName();
void setName(string);
int getYear();
void setYear(int);
void printInfo();
private:
string name;
int yearBuilt;
};
Ship:: Ship()
{
name = "";
yearBuilt = 0;
}
Ship:: Ship(string theName, int theYear)
{
name = theName;
yearBuilt = theYear;
}
string Ship::getName()
{
return name;
}
void Ship::setName(string newName)
{
name = newName;
}
int Ship:: getYear()
{
return yearBuilt;
}
void Ship:: setYear(int newYear)
{
yearBuilt = newYear;
}
void Ship:: printInfo()
{
cout << "Name: " << name << endl;
cout << "Year built: " << yearBuilt << endl;
}
int main()
{
Ship lilCutie;
lilCutie("Boat", 1993);
lilCutie.printInfo();
return 0;
}
There is core difference between line
Ship LilCutie;
and
LilCutie("Boat", 1993);
First is a definition. Definition describes and initializes a variable. Second is a statement to execute, consisting of call operator (operator()).
As you didn't defined operator() for type ship, the second line is illegal. Constructors are called as part of creation and initialization of object. So you should write either:
Ship LilCutie("Boat", 1993);
or
Ship LilCutie;
LilCutie = Ship("Boat", 1993);
Of course, in second case first line executes default constructor, second line creates a new object of Ship class and performs assignment of its value by default operator (will work fine in case of string class field, which had own operator= defined, would do only a shallow copy otherwise). Parenthesis () in both lines are syntax for initialization.
You can call constructor with no parameter, then use setters to set value to it:
Ship lilCutie;
lilCutie.setName("Boat");
lilCutie.setYear(1993);
Also you can do that by calling constructor with parameters:
Ship lilCutie("Boat", 1993);
In this Code a method name setname().
In this method I am using parameter (Char *aname), argument "Name_Student" (When calling).
But getting error: "deprecated conversion from string constant to 'char*' [-Wwrite-strings]"
#include <iostream>
#include <string>
using namespace std;
class student
{
int rollno;
char *name;
public:
void setname( char *aname);
void setrollno(int arollno);
char getname() {return *name;}
int getrollno() {return rollno;}
};
void student::setname(char *aname)
{
name = aname;
}
void student::setrollno(int arollno)
{
rollno = arollno;
}
int main()
{
student astudent;
astudent.setname("Name_Student"); //Getting Error Here
astudent.setrollno(10);
astudent.getname();
astudent.getrollno();
return (0);
}
I want to know why I am getting this error. Can Anyone explain different scenarios to understand this.
When I am using casting in argument at the time of calling
.setname((char*)"Name_Student"); //Working Fine
When I am storing this string in an array and passing that array like
char name_s[] = "Name_Student";
.setname(name_s); // working fine
Probably what you are looking for is answered here.
Also here is a reply to the comment about strings that I have posted below the question:
In both C/C++ you can choose whether to pass by reference or value. There are two ways to do that - the * (pointer to) operator and & (address of) operator. However working with pass by value (not by reference) is totally okay in your case:
#include <iostream>
#include <string>
using namespace std;
class student
{
int rollno;
string name;
public:
void setname(string name) { this->name = name; }
void setrollno(int rollno) { this->rollno = rollno; }
string getname() { return name; }
int getrollno() { return rollno; }
};
int main()
{
student astudent;
astudent.setname("Name_Student"); // here you pass by value
astudent.setrollno(10);
astudent.getname(); // name is set, so everything is okay :)
astudent.getrollno();
return (0);
}
If you really want to go into the whole pass by reference thing you can easily modify the setname() function like this (you'll also have to modify the name member with string* name and the getname() with return *name):
void setname(string& name) { this->name = name; }
In this case however a call like
astudent.setname("Name_Student");
is not possible and you have to first create the object and then pass it to the function:
string newName = "Name_Student";
astudent.setname(newName);
This is useful in case you want to change the name outside the class however it might be viewed as something against the principles of OOP since altering an object's content should be done only via some strictly defined by the class it represents routines and not just like that.
Here is a redo of your code with a small example to illustrate what I mean:
#include <iostream>
#include <string>
using namespace std;
class student
{
int rollno;
string* name; // very important! otherwise you will just store a COPY of the new name instead of a reference to the object that was passed to setname()
public:
// here we pass by reference a string object!
void setname(string& name) { this->name = &name; }
void setrollno(int rollno) { this->rollno = rollno; }
string getname() { return *name; }
int getrollno() { return rollno; }
};
int main()
{
student astudent;
string str = "Name_Student";
astudent.setname(str); // we pass by reference here!
cout << astudent.getname() << endl;
str += "LALALA"; // because we have passed the string object by reference to the astudent object we can change its contents outside the class without using the setter provided by the class
cout << astudent.getname() << endl;
return (0);
}
The output from the code above will be:
Name_Student
Name_StudentLALALA
Then again in your case I do not believe you need any passing by reference. And a bit of advice - try to use the features provided by C++ when programming in C++. Although there are of course situation when you might want to stick to the old char* way of doing things in your case it just poor coding style. std::string also provides the c_str() function, which returns a C-string (see here for more information).
You should insert 'const' before 'char*', however this question has already been answered here: How to get rid of `deprecated conversion from string constant to ‘char*’` warnings in GCC?
Unless you have a specific reason to use char* you should use std::string. I think the idea of using std::string* is a terrible idea because the lifetime of the name of the student is separate from the student object. Consider the following code:
student get_student()
{
// get the student from the database
string name = "some name";
int rollno = 1;
student s;
s.setname(name);
s.setrollno(rollno);
return s;
}
If you then try to use the student's name you will be referencing an object that no longer exists. You can try it with:
student s = get_student();
cout << s.getname() << endl;
I think the best option is to use string for the name. That way you don't have to worry about memory allocation and lifetime management. You should also have a constructor instead of just setters (unless you are going for POD).
class student {
int rollno;
string name;
public:
student(const string& name, int rollno): name(name), rollno(rollno) {}
void setname(const string& name) { this->name = name; }
void setrollno(int rollno) { this->rollno = rollno; }
const string& getname() { return name; }
int getrollno() { return rollno; }
};
If your setname takes the argument as a const string& then you can still use setname("Name") because this will create an rvalue, which can bind to const reference.
int main(int argc, char *argv[]) {
student astudent("Student's Name", 10);
cout << "Roll #: " << astudent.getrollno() << '\n';
cout << "Name: " << astudent.getname() << '\n';
astudent.setname("New name");
cout << "Name: " << astudent.getname() << '\n';
string n{"Yet Another Name"};
astudent.setname(n);
cout << "Name: " << astudent.getname() << '\n';
return (0);
}
In the following code, I'm not able to pass a temporary object as argument to the printAge function:
struct Person {
int age;
Person(int _age): age(_age) {}
};
void printAge(Person &person) {
cout << "Age: " << person.age << endl;
}
int main () {
Person p(50);
printAge(Person(50)); // fails!
printAge(p);
return 0;
}
The error I get is:
error: invalid initialization of non-const reference of type ‘Person&’ from an rvalue of type ‘Person’
I realize that this is something to do with passing an lValue to a function expecting a rValue... Is there a way to convert my lValue to rValue by using std::move or something? I tried taking a constant parameter, but that does not seem to work.
Simply make your print function take your argument by const&. This is also logically right as it doesn't modify your argument.
void printAge(const Person &person) {
cout << "Age: " << person.age << endl;
}
The actual problem is the other way around. You are passing a temporary(rvalue) to a function which expects an lvalue.
Or, if you have a C++11-compliant compiler, can use the so called universal reference approach, which, via reference collapsing rules, can bind to both lvalue and rvalue references:
#include <iostream>
using namespace std;
struct Person {
int age;
Person(int _age): age(_age) {}
};
template<typename T> // can bind to both lvalue AND rvalue references
void printAge(T&& person) {
cout << "Age: " << person.age << endl;
}
int main () {
Person p(50);
printAge(Person(50)); // works now
printAge(p);
return 0;
}
Or, in C++14,
void printAge(auto&& person) {
cout << "Age: " << person.age << endl;
}
Your code doesn't work if you run g++ or gcc compilers. You need to add const to void printAge(const Person &person). However, in Visual Studio it will work fine. I've tested for VS2010 and VS2012 and in both the following code works fine.
#include<iostream>
using namespace std;
struct Person {
int age;
Person(int _age): age(_age) {}
};
void printAge(Person &person) {
cout << "Age: " << person.age << endl;
}
int main () {
Person p(50);
printAge(Person(50)); // DOES NOT fail!
printAge(p);
return 0;
}