I've been programming in java and AS3 and C# for some time, and decided to give C++ a try... So, I decided to create a simple program to see how objects work here. I have two files:
Human.h
#pragma once
#include <string>
#include <iostream>
using namespace std;
class Human
{
private:
int _age;
string _name;
bool _gender;
public:
void setAge(int);
void setName(string);
int getAge();
string getName();
bool getGender();
Human(int age, string name, bool gender)
{
setAge(age);
setName(name);
_gender = gender;
}
~Human()
{
}
};
int Human::getAge(){
return _age;
}
string Human::getName(){
return _name;
}
bool Human::getGender(){
return _gender;
}
void Human::setAge(int val){
}
void Human::setName(string val){
_name = val;
}
And Main.cpp
#include <iostream>
#include "Human.h"
#include <string>
using namespace std;
void main(void){
Human *me;
me = new Human(27,"Mr Miyagi",true);
cout << "My name is "+me.getName()+" and I am "+me.getAge()+" years old";
}
What I get is a red line under the "me" word, and an error C2228: left of '.getName' must have class/struct/union
me is a pointer to a Human - so you need to use ->
cout expects you to use the << operator.
main should not return void, but int.
always delete what you new
int main() {
Human *me;
me = new Human(27,"Kostas Loupasakis",true);
cout << "My name is " << me->getName() << " and I am " << me->getAge() << " years old";
delete me;
}
Alternatively, you can do without the pointer, and use .:
int main() {
Human me(27,"Kostas Loupasakis",true);
cout << "My name is " << me.getName() << " and I am " << me.getAge() << " years old";
}
The first variant above allocates a Human from the free store, called heap - similar to java. You need to explicitly delete in c++ though.
The second variant allocates a Human on stack - java can only do this with primitive types (int, float) and so on, c++ can do this with any object. In this case, me is automatically destructed when it goes out of scope, at the final '}' in main.
It should be -
cout << "My name is " << me->getName() << "and I am " << me->getAge() << " years old";
me is a pointer to an object. So, it's members should be accessed by operator ->.
Also, note that Human::setAge() function does nothing.
You have declared me as a pointer. Either remove the * on the declaration, or Use me->GetName() etc to use it.
= = = edit = = =
Since there is no default constructor, the * must remain. Either that or change it to
Human me(27, "name", true);
Others have addressed the direct problem you asked about. If you will indulge me, let me address a tangential issue.
Here is what you started with.
void main()
{
// You could combine these two lines like this:
// Human *me = new Human(27,"Kostas Loupasakis",true);
Human *me;
me = new Human(27,"Kostas Loupasakis",true);
cout << "My name is "+me->getName()+" and I am "+me->getAge()+" years old";
}
I can't speak to AS3, but in java and C#, you have the garbage collector to clean up allocated memory. There is no such beast in C++, so you have to clean up the memory yourself like this.
void main()
{
Human *me = new Human(27,"Kostas Loupasakis",true);
cout << "My name is "+me->getName()+" and I am "+me->getAge()+" years old";
delete me;
}
The call to new allocates the Human object on the heap, and delete frees the memory when you are done with it. Here is a better way to do it.
void main()
{
Human me(27,"Kostas Loupasakis",true);
cout << "My name is "+me.getName()+" and I am "+me.getAge()+" years old";
}
In this case, space for the Human object is reserved on the stack as opposed to the heap. Thus, the space is automatically reclaimed when the function exits. Additionally, you can use the . notation instead of the -> notation since you are dealing with an object as opposed to a pointer.
I hope this helps.
the object 'me' is actually a pointer, so therefore you will need to use an arrow instead of a dot.
me->getname();
will solve the error.
Related
The bellow code works fine unless I don't define destructor for the class.
But it produces wrong result when I define destructor . In the destructor part I freed up the memory that was created in constructor .I think its my job to do so . But in this case doing this make my program to run with undesired output. I am very frustrated with the program. Please help me out. I can not figure out any problem with the code. All things seem to okay for me.
Here I have made an array of objects of type list. Then I assigned values to the objects individually with the help of constructor. But it seems that the values are not getting initialize appropriately .But I think had not made any mistake there to initialization process. Then when I print the object data with member function display it could not produce the desire result. Although it prints the int and float data member properly. it can not print the char* data member properly.
#include <iostream>
#include <cstring>
#include <iomanip>
using namespace std;
class list
{
private:
char* name;
int code;
double cost;
public:
//constructor
list()
{
}
list(const char* name,int code,double cost)
{
int len=strlen(name);
this->name=new char[len+1];
strcpy(this->name,name);
this->code=code;
this->cost=cost;
}
//mem fun
void display(void)
{
cout.precision(2);
cout.setf(ios::fixed);
cout << setw(20) << this->name << setw(10) << this->code << setw (12) << cost << endl;
}
//destructor
~list()
{
delete[] this->name;
}
};
int main()
{
list item[3];
item[0]=list("Turbo C++",1001,250.95);
item[1]=list("C Primer",905,95.70);
item[2]=list("C++ Book",105,30);
cout << setw(20) << "NAME" << setw(10) << "CODE" << setw(12) << "COST" << endl;
for(int i=0;i<3;i++)
item[i].display();
return 0;
}
You are copying all your list items because you have an array of objects (not not pointers) - since it is just a "shallow copy" you have two instances with the same name pointer hence the "double free" message.
There are a couple of approaches to fix it:
You could define an operator= that makes a duplicate string. That
works but you still have unnecessary copies.
You could have an array of pointers in main (instead of instances).
You could have a set() method to set the values inside an existing instance (e.g. item[0].set("Turbo C++", 1001, 250.95); )
I understand that void returns no values.
So how does it work in conjuncture to a function?
My understanding is that the purpose of a function is to return a piece of information after doing something with it.
so why would I want to return no value, and how would this be beneficiary?
My understanding is that the purpose of a function is to return a
piece of information after doing something with it.
In some (most of the) programming languages, functions have side effects also. Purpose of some functions is limited only to side effects and return value is not necessary. Such functions have void return type.
Some examples of side effects may be:
Update a global
File operation, logging etc where user doesn't want to know the status of operation
Freeing resources
C++ Programming Language Stroustrup 4th Edition book
When declaring a function, you must specify the type of the value returned. Logically, you would expect to be able to indicate that a function didn’t return a value by omitting the return type. However, that would make a mess of the grammar (§iso.A). Consequently, void is used as a ‘‘pseudo return type’’ to indicate that a function doesn’t return a value.
Edit:
When you don't expect something in return to the calling function, we use void function.
If void() does not return a value, why do we use it?
It can be pretty useful for modularizing output.
I'll provide you with an example:
#include <iostream>
#include <string>
using namespace std;
void displayMessage(string fName, string mName, string lName, string id);
int main() {
string student[4] = { "Mike", "L.", "Jason", "c23459i" };
displayMessage(student[0], student[1], student[2], student[3]);
return 0;
}
void displayMessage(string fName, string mName, string lName, string id)
{
double PI = 3.14159265359;
cout << "Student " << " information:"
<< "\nFirst name: " << fName
<< "\nMiddle Initial: " << mName
<< "\nFirst name: " << lName
<< "\nID: " << id
<< "\nThe Circumference of a circle with the radius of 2: " << (2*PI*2);
}
You can use void functions IF you don't need to return a value. If you plan to do calculations and return a value such as an int, use a function declaration with the return type of int.
when i compile the program i get an error about int when i create a bookClass object using the 2 argument constructor. the error has somerthing to do with the integer argument parsed to the constructor. the program is:
#include <iostream>
#include <string>
using namespace std;
class bookClass{
private:
string bookName;
int bookNumber;
public:
void setName(string c){
bookName=c;
}
void setNumber(int d){
bookNumber=d;
}
string getName(){
return bookName;
}
int getNumber(){
return bookNumber;
}
bookClass(string a, int b){
bookName=a;
bookNumber=b;
}
};
int main()
{
int numberr;
string name;
cout << "Enter the book name: ";
cin >> name;
cout << "\nEnter the book number: ";
cin >> numberr;
bookClass book=new bookClass(name, numberr);
cout << "\n\nThe book " << book.getName() << " has book number " <<
book.getNumber() << endl;
return 0;
}
Compiling your code I didn't get the error you suggested. However, there is an issue with this line:
bookClass book = new bookClass(name, numberr);
C++ is not Java. new returns a pointer to memory dynamically allocated for the given class.
What you want is just:
bookClass book (name, numberr);
The problem with your code is simple. I suppose you were programming in Java or C# before C++. In C++ we call new operator only if we want to create an object explicitely on heap (and get a pointer to it).
bookClass* book=new bookClass(name, numberr);
However, now you are in troubles because you are calling book.getName() where book is of type pointer to something and it has no member getName(). You have to first dereference that pointer and then call a member function (*book).getName(); or simply book->getName();.
However, since C++'s objects do not have to be on the heap (Java objects have to) you can create an object without new operator using bookClass book(name, numberr);
I want to output the values of the private class members Bankcode and AgentName. How can I do this from within my main() function, or in general, outside of the BOURNE class.
My initial code attempts are below:
#include <iostream>
#include <string>
using namespace std;
class BOURNE
{
string Bankcode ={"THE SECRET CODE IS 00071712014"} ; /*private by default*/
string AgentName={"Jason Bourne"}; /*private by default*/
public:
void tryToGetSecretCodeandName(string theName ,string theCode); //trying to get the private
void trytoGetAgentName( string name); // try to get name
};
//***********************defining member function**************************************
void BOURNE::tryToGetSecretCodeandName(string theName, string theCode) //member defining function
{
Bankcode=theCode; //equalling name to the code here
AgentName=theName; //the samething here
cout<<theCode<<"\n"<<theName; //printing out the values
}
//************************main function*****************************
int main()
{
BOURNE justAnyObject; //making an object to the class
justAnyObject.tryToGetSecretCodeandName();
return 0;
}
Third Answer
Your code has two 'getter' style functions, but neither one takes no arguments. That is, both of your functions require arguments to be passed.
Your main function is calling get...CodeandName(), which has no arguments. As such, you get a compiler error, probably complaining about valid signatures, or arguments passed.
Edited Answer
If you only want to get the values, the typical (as far as I am aware) implementation is something like
std::string BOURNE::getCode()
{
return Bankcode;
}
std::string BOURNE::getName()
{
return AgentName;
}
int main()
{
BOURNE myAgent;
cout<< "The agent's name is : " << myAgent.getName() << endl;
cout<< "The agent's code is : " << myAgent.getCode() << endl;
}
Original Answer, left in because I feel like it's more useful
I suspect what you're asking is if you could do something like
void BOURNE::tryToGetSecretCodeandName(string theName, string theCode)
{
if (Bankcode == theCode) {
cout<< "You correctly guessed the code : " << Bankcode << endl;
}
if (AgentName == theName) {
cout << "You correctly guessed the agent's name : " << AgentName << endl;
}
}
This will allow you to repeatedly guess at the name, and get output when you're correct.
If you wanted to disable this kind of guessing, then you could consider creating a new class (possibly derived from/based on std::string - but see this question for reasons to be careful!) and implement an operator== function which always returned false.
Can I initiate a string array and pass it as a function that initializes it. I know this sounds redundant, but basically I want to initiate a string array and then pass it to a variable so that I can use it later? Something like this:
This is the .h:
class ScreenBasics{
void setupAnswers(int &_numberOfAnswers, string *_answersText);
string *answersText;
{
This will be the implementation .cpp
void ScreenBasics::setupAnswers(int &_numberOfAnswers, string *_answersText){
answersText = _answersText; // this is where I get confused cause I don't know if I should initiate my string pointer using new like answersText = new string(_numberOfAnswers);
{
so in the main.cpp I can do something like this:
int main( ) {
ScreenBasics basics;
int numberOfAnswers = 4;
string newAnswers [] = { "Good", "Superb", "Great", "Perfect"};
basics.setupAnswers(numberOfAnswers, newAnswers);
// let's say I want to call some of those answers later
for ( int i = 0; i < numberOfAnswers; i++){
cout << basics.answersText[i] << endl;
}
}
Thanks!
Have you thougt about using structs? Both classes and structs can have a mixture of public and private members, can use inheritance, and can have member functions. I would recommend using structs as plain-old-data structures without any class-like features, and using classes as aggregate data structures with private data and member functions.
Your code would look like the following:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
struct movies_t {
string title;
int year;
} mine, yours;
int main ()
{
string mystr;
mine.title = "2001 A Space Odyssey";
mine.year = 1968;
cout << "Enter title: ";
getline (cin,yours.title);
cout << "Enter year: ";
getline (cin,mystr);
stringstream(mystr) >> yours.year;
cout << "My favorite movie is:\n ";
printmovie (mine);
cout << "And yours is:\n ";
printmovie (yours);
return 0;
}
void printmovie (movies_t movie)
{
cout << movie.title;
cout << " (" << movie.year << ")\n";
}
Please let me know if you have any questions!
It sounds like your class should use a constructor to initialize the pointer.
class ScreenBasics
{
ScreenBasics(std::string* _answersText, std::size_t size)
: answersText(new std::string[size])
{
// copy values from _answersText to answersText
}
};
Note that since you are allocating a resource dynamically, you will need to implement The Rule of Three: that is, you need to create a copy-constructor, copy-assignment operator and destructor. This is because their default implementations do not semantocally conform to our requirements. For instance, the default copy-constructor and copy-assignment operator perform shallow copies (that is, they copy the pointer but not what it points to). Also, the destructor doesn't free the memory allocated my new[]. You will need to provide your own definition of the destructor that calls delete[].
Fortunately, all this can be avoided by using the standard library container std::vector, which is a dynamic array class that handles the memory allocation for you. The default implementations of the aforementioned constructors will correctly copy/copy-assign a vector if the need be:
class ScreenBasics
{
ScreenBasics(std:vector<std::string> _answersText)
: answersText(_answersText)
{
}
};
Notice that the size also didn't have to be passed as a parameter. A vector maintains its size internally.