Assistance with Person Class - c++

I need help with figuring out how to code the given specifications since I'm really lost in how to use the three different source files and what needs to go in all of them.
#include <iostream>
#include<string>
using namespace std;
class Person
{
public:
Person();
string getName();
int getAge();
void setName(string newName);
void setAge(int newAge);
void display();
private:
string name;
int age;
};
This is all I have for Person.h so far.
Specification
1. Given Person.h
1(a). Add a parametrized constructor that uses an initializer list for name and validates ago > 0
1(b). Create a Person.cpp that implements the functionality of Person.h
Create PersonTest.cpp that demonstrates the features of class Person

What do you mean by three different source files? If you mean Person.h, Person.cpp, and PersonTest.cpp, see below
a .h file (you should actually be using a .hpp file for c++ but it still technically works) is whats called a header file. This is where you would pretty much just name the class and all its attributes/methods, its the bare bones of the class that shows what the class is capable of doing without actually showing how its all done.
Person.cpp would be the file where you implement everything from the .h class. the top of your .h file should have something like this at the top:
#include "Person.cpp"
This tells the .h file where to look for the implementation of the methods you previously declared. To implement a method, all you need to do is something like inside of the cpp file `
void Person::setAge(int newAge) {
---implementation---
}
the "Person::" just shows that you are doing something inside of the Person class.
The third file is probably where your int main() is going to be, and make sure that at the top, it also has the #include for the header. Here is where you do what you want to test if your class is actually working, like checking that your outputs match what you expect, etc etc.
I hope this clarified a little of what you needed!

Given you know what a constructor is, you should add to this file another constuctor :
Person(string name,int age);
in the file Person.cpp you develop all the functions defined in Person.h
The file PersonTest.cpp should have a main function that calls instances of Person and prove your class works

Related

Why does the C++ Compiler not find the function definitions? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I wrote some code trying to understand the relationship between compiling and linking - and also to see where and if function declarations have to be repeated in source files.
The two files I wrote are:
Person.cpp:
#include <string>
class Person {
public:
Person(std::string name) {
(*this).name = name;
};
std::string getName() {
return name;
};
std::string name;
};
and the file
PersonMain.cpp:
#include <iostream>
class Person {
public:
Person(std::string);
std::string getName();
std::string name;
};
int main(){
Person* charlie = new Person("Charlie");
std::cout << "Hi, my name is " << charlie->getName();
}
I repeat the Class Person and Class Person function declarations (not the definitions) in the PersonMain.cpp.
I now compile and link the two files using the gcc C++ Compiler:
g++ *.cpp -o runthis.exe
I then get the following error message:
PersonMain.cpp:(.text+0xfe): undefined reference to
Person::Person(std::basic_string<char,
std::char_traits<char>,std::allocator<char> >)'
PersonMain.cpp:(.text+0x13c): undefined reference to
Person::getName()' collect2.exe: error: ld returned 1 exit status
It seems the Person Class methods are not found when linking. Why is that? How can I heal this?
ADDENDUM:
I repeated the declaration of Person in PersonMain.cpp explicitly, and didn't but the redeclaration into a header file as would be done normally. So I've done the preprocessor step here already. This faq suggests that:
[The Preprocessor] works on one C++ source file at a time by replacing
include directives with the content of the respective files (which is usually just declarations)[...]
and later on:
[The Linker] links all the object files by replacing the references to
undefined symbols with the correct addresses. Each of these symbols
can be defined in other object files or in libraries.
I add this remark becaue #engf-010 said that a Compilation Unit that has code that isn't actually used in that compilation unit is not compiled, even if it is needed in other compilation units. enf-010 suggests that I put the definition and declaration into the header file, but the faq article says that only the declarations should go there, the definitions can be elsewhere.
Usually one splits declarations and definitions into .h and .cpp files respectively.
Your code would look something like this:
person.h - declarations:
#include <string>
class Person {
public:
Person(std::string n);
std::string getName() const;
std::string name;
};
person.cpp - implementation:
#include <string>
#include "person.h"
Person::Person(const char* n) : name(n) { }
std::string Person::getName () const { return name; }
and personmain.cpp - where you use your class Person:
#include <iostream>
#include "person.h"
int main()
{
Person* charlie = new Person("Charlie");
std::cout << "Hi, my name is " << charlie->getName ();
}
Like #engf mentioned, essentially, what you got in your code is double definition of Person and no implementation. You can't easily define Person in main file and implement Person::Person() somewhere else (and you should not), in another translation unit (i.e., in person.cpp), without letting the compiler know what you implement. You can't forward-declare Person and use it in personmain.cpp like this:
class Person;
...
Person* charlie = new Person("whatever");
because compiler should know complete type to emit code constructing the Person-object. You can't have two definitions of Person. You can't implement members of Person without definitions, accessible to all users of your code. So, what you left with is the scheme like this above.
To elaborate a bit more on compilation and linking, very roughly, when compiler sees a reference to symbol not defined locally in the same translation unit, it puts appropriate record into object file. When this object file is passed to the linker (possibly, along with a bunch of other object files and libraries), linker should resolve such records to symbols (functions, variables etc.) found somewhere in input object files or libraries. If it succeeds in that, it combines all the referenced code into single image. In your case the linker failed to resolve referenced symbol Person::Person for constructor. Probably this is not bad Q&A to start.
what you've got is a definition in one source file and a declaration in the other source file.
When the source file containing the definition is compiled ,the compiler comes to the conclusion that there isn't any 'real' code to generate ,because you didn't use the class.
So you end up with an empty object file.
You can define a class in a source file but if you don't use that class in that file it is tossed away as not being used.
If you use that class in other source files (through it's declaration) the compiler generates code for member accesses ,but those are not found during linking.

setter in class won't set variable

I'm currently trying to make a game in C++. In my code I'm trying to nest my variables so that my main doesn't have a lot of includes. My problem right now though is that the value of my variables in my class aren't changing. Stepping through the code it shows it setting the value, but it doesn't work. Anyone know what's going on? Thank you in advance.
This is what I have so far:
Location.h
#ifndef LOCATION_H
#define LOCATION_H
#include <string>
class Location
{
public:
Location(void);
Location(std::string name);
~Location(void);
std::string GetName();
void SetName(std::string value);
private:
std::string m_Name
};
#endif
Location.cpp
#include "Location.h"
Location::Location(void): m_Name("") {}
Location::Location(std::string name): m_Name(name) {}
Location::~Location(void)
{
}
std::string Location::GetName()
{return m_Name;}
void Location::SetName(std::string value){m_Name = value;}
PlayerStats.h
#ifndef PLAYERSTATS_H
#define PLAYERSTATS_H
#include "Location.h"
class PlayerStats
{
public:
PlayerStats(void);
~PlayerStats(void);
Location GetLocation();
void SetLocation(Location location);
private:
Location m_Location;
};
#endif
PlayerStats.cpp
#include "PlayerStats.h"
PlayerStats::PlayerStats(void): m_Location(Location()) {}
PlayerStats::~PlayerStats(void)
{
}
Location PlayerStats::GetLocation(){return m_Location;}
void PlayerStats::SetLocation(Location location){m_Location = location;}
main.cpp
#include <iostream>
#include "PlayerStats.h"
using namespace std;
PlayerStats playerStats = PlayerStats();
int main()
{
playerStats.GetLocation().SetName("Test");
cout<< playerStats.GetLocation().GetName()<<endl;
return 0;
}
Your immediate issue is that
Location GetLocation();
returns a copy of the location, so when you call SetName here:
playerStats.GetLocation().SetName("Test");
You're changing the name of the temporary copy, and the change is lost as soon as the semicolon is hit.
More broadly, this kind of design (nesting classes and nesting includes so that main doesn't have a lot of includes, and using a.b.c() style code to access nested members) isn't great C++ style:
Having a bunch of source files that (transitively) include a bunch of header files means that changing a single header file will trigger recompilations of a bunch of source files. Compile times can be a significant issue in larger C++ projects, so reducing compile times by controlling #include's is important. Read up on "forward declarations" for more information.
Writing code like a.b.c() is considered bad object-oriented design, because it reduces encapsulation: not only does the caller have to know about a's details, it has to know about b's also. Sometimes this is the most expedient way to write code, but it's not something to be blindly done just to reduce #include's. Read up on "Law of Demeter" for more information.
If you want to set the result of playerStats.GetLocation(), you could make GetLocation() pass-by-reference (use ampersand, &, on the return argument). Otherwise you are just setting values in a temporary copy of PlayerStats::m_Location.
Alternatively, you could use the SetLocation() function.

Class pointer to different .h file

Helo stack people, I need your help in work I make. So I have to .h files first one is Course and the second is Student and I try to create function call getCourses but Unfortunately It's not going so well.My realization "Course ** courses" do not pass compiling and I do not know why not. I would appraise if you can help me to Understand my mistake and help me to fix them thanks.
getCourse - return list of courses
my Course .h file
#ifndef _CORSE_H
#define _CORSE_H
#include <iostream>
#include "Student.h"
class Course
{
public:
void init(std::string getName, int test1, int test2, int exam);
std::string getName();
int* getGrades();
double getFinalGrade();
private:
std::string _name;
int _exam;
int _test1;
int _test2;
};
#endif
My Student .h file-
#ifndef _STUDENT_H
#define _STUDENT_H
#include <iostream>
#include "Course.h"
class Student
{
public:
void init(std::string name, Course** courses, int crsCount);
std::string getName();
void setName(std::string name);
double getAvg();
int getCrsCount();
Course** getCourses();
private:
std::string _name;
Course** courses;
int _crsCount;
};
#endif
My get course function -
Course** student::getCourses()
{
return(this->courses);
}
The problem in the "Course** getCourses();"initialization and this applies also to the init function and Course** getCourses(); function.
error C4430: missing type specifier - int assumed. Note:C++ doe not support default-int
You have a circular dependency - each header tries to include the other, and you end up with one class defined before the other. This gives errors, because you have to declare a type before you can use its name.
Course doesn't depend on Student at all, so just remove the #include from that file.
The definition of Student only uses pointers to Course so it doesn't need the full definition. It only needs to know that the class exists, so you can replace the #include with a declaration:
class Course;
A couple more points:
both headers should include <string> since they use std::string; but not <iostream> since they don't use any I/O streams;
names beginning with an underscore and a capital, like _CORSE_H, are reserved. You should remove the underscores.
you've mis-capitalised Student in the final code snippet.
Besides what Mike Seymour wrote your course function uses lowercase student in
Course** student::getCourses()
Whereas you declared the class with a capital S. Case does matter.

With or without class wrappered in C++

I have a basic question since I havent used C++ in a while.
I have a header file like so:
It will remain the same, however the cpp file will change
#ifndef DOG_H_
#define DOG_H_
class Dog : Animal {
private:
std::string breed;
public:
Dog(std::string name, int age, std::string);
};
#endif /* DOG_H_ */
and then CPP version 1:
#include "Dog.h"
Dog::Dog(std::string name, int age, std::string breedIn){
Animal(name, age);
breed = breedIn;
}
or CPP Version 2:
#include "Dog.h"
class Dog{
Dog::Dog(std::string name, int age, std::string breedIn){
Animal(name, age);
breed = breedIn; // the var name breed does not resolve
}
};
The difference between version 1 and version 2 is that the 2nd one is wrapped in the class definition.
Why should I do one and not the other.
Secondly, in the second version, the variable name breed does not resolve. Why is that?
Q: in the second version, the variable name breed does not resolve. Why is that?
A: Because it's wrong.
You declare your class once, e.g. in the header.
You may define your method implementations either in-line (in the header itself, when you declare the class), or in a separate .cpp (as you did in example 1).
Thess links might help explain further:
http://www.cplusplus.com/doc/tutorial/classes/
http://www.cprogramming.com/declare_vs_define.html

Is this the correct way to implement composition in C++?

A chest is composed of treasure.
I've implemented it the following way:
treasure.hpp
#pragma once
class Treasure{
public:
protected:
private:
//data members
int gold;
};
chest.hpp
#pragma once
class Chest{
private:
#include "treasure/treasure.hpp"
public:
protected:
private:
//data members
Treasure treasure;
};
**Assume both header files get compiled with their corresponding ".cpp"s to create object files.*
Is it appropriate to include the header file for treasure inside the class declaration of chest?
It makes sense to me, because I get the following behaviour:
**Main can not create or directly access Treasure.*
#include "chest.hpp"
int main(int argc, char** argv){
Chest chest;
}
I've never seen it this way, so I'm not sure if it is bad practice.
In regards to composition, which method is preferred:
including the header before the class declaration; having main indirectly include Treasure?
including the header privately inside the class declaration as shown above?
I would #include "treasure.hpp" at the top of chest.hpp before the Chest class declaration.. Not all treasure is found in a chest. If main() wants to create a Treasure that is not in a Chest, it should be allowed to do so.
On the other hand, I certainly can imagine times where a private class would be useful. In such a situation, I would code the private class directly inside the outer class rather than #include it.
I would have main include the file indirectly (treasures include is at the top of chest). It does not make very much sense to have multiple includes. In fact, that's one of the main uses of those precompiler directives; to prevent compilation errors due to a file being included multiple times.
If you do it the other way you couldn't do things main like; create new treasure and add it to your chest or take treasure out of your chest and work with it independently. That implementation would only make sense if the object B was used exclusively by object A.