How can you access private string variables using member functions? - c++

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.

Related

Set and get member functions manipulation of data members

So I'm an newbie to programming and I have encountered a
case for which I suppose qualifies as an authentic question
in this awesome forum. Is there a way to write statements inside my get functions so that I can obtain all the changed data member values without having to create multiple get functions
for each data member?
Regards
I am practicing building programs which are easy to maintain by localizing the effects to a class's data members by accessing and manipulating the data members through their get and set functions. In this regard I have two data members for which I wish to change. After compiling, the set functions works well by changing the values but the get functions can only return one of the data member values at a time.
class GradeBook
{
public:
void setCourseName(string code,string name)
{
CourseCode = code;
CourseName = name;
}
string getCourseName()
{
return CourseCode;
return CourseName;
}
void displayMessage()
{
cout<<"Welcome to the GradeBook for: \n" <<getCourseName()
<<endl;
}
private:
string CourseName;
string CourseCode;
};//end class GradeBook
After compiling and running the program, the program outputs the CourseCode but the CourseName doesn't get displayed. I had to create two get functions each to obtain the two data members. I don't want to have 2 get functions to obtain the data member values. I just want to use one get function to keep the code at minimum.I wish to use one get function to return two values for each data member. I have already tried using one return statement and separated the data members with a comma.
Your idea of using return twice cannot work, the first return will return control to the caller and the second will never be executed. You should have got warning about it from your compiler.
I believe that an initial solution could be to use std::pair (docs: https://en.cppreference.com/w/cpp/utility/pair), see snippet below.
NOTE: using namespace std; (which is most likely what you are doing in the code you do not show), is a bad practice, consider using the fully qualified name
#include <string>
#include <utility>
#include <iostream>
//Bad practice, I added it only to keep differences with OP code small
using namespace std;
class GradeBook
{
public:
void setCourseName(string code,string name)
{
CourseCode = code;
CourseName = name;
}
std::pair<string, string> getCourseName()
{
return {CourseCode, CourseName};
}
void displayMessage()
{
//only in C++17
auto [code, name] = getCourseName();
cout<<"Welcome to the GradeBook for: \n" << code << " - " << name
<<endl;
}
private:
string CourseName;
string CourseCode;
};//end class GradeBook
Note that auto [code, name] is a feature called structured binding, available only in C++17, if you have an older compiler, you have to return a std::pair<std::string, std::string> and access its elements using the member variables first and second.
Now, std::pair is good for this contrived example, but, for your case, you might want to consider doing something a bit more readable, because the elements of the pair have the same type so the user of your library will have difficulties remembering what is the first and second element. So you might want to use a custom-made struct with some more meaningful names.
#include <string>
#include <utility>
#include <iostream>
//Bad practice, I added it only to keep differences with OP code small
using namespace std;
struct CourseCodeAndName{
std::string code;
std::string name;
};
class GradeBook
{
public:
void setCourseName(string code,string name)
{
CourseCode = code;
CourseName = name;
}
CourseCodeAndName getCourseName()
{
return {CourseCode, CourseName};
}
void displayMessage()
{
auto codeAndName = getCourseName();
cout<<"Welcome to the GradeBook for: \n" << codeAndName.code << " - " << codeAndName.name
<<endl;
}
private:
string CourseName;
string CourseCode;
};//end class GradeBook
See this example. Alternatively you can use std::tuple.
class GradeBook
{
/* ... */
public:
std::pair<std::string, std::string> get(){
return std::make_pair(CourseName, CourseCode);
}
};
int main()
{
GradeBook book1("Hello","World")
auto result = book1.get();
cout << result.first << result.second;
}
If you write:
return x,y;
or:
return x;
return y;
You should know that in first case you get the last value (you get y), and in second case you get the value of first return (you get x, because as soon as compiler see return, function will return the value, and then function will go in epilogue state (cleaning of stack memory assigned to function, both inline and non-inline function).
And about the use of get function it's normal. If you want to use the value to do something of logic (not to display), yes you should use a lot of get function. Instead if you want to display the values, use a void function, for example "void printData();", and inside it write code to print data. You probably setted the class variables as private (following the encapsulation rules) so you will have access to them inside the print function.

Creating a class member that is automatically calculated from other class members?

I'm an absolute newbee when it comes to programming and I'm trying to teach myself the basics by just solving some easy "problems" in C++.
I have searched the web for an exact answer to my question before posting it here and haven't found one so far, however that may be because of (1).
So, what I'm looking for is a way to declare a class member that gets automatically calculated from other members of the same class, so that the calculated class member can be used just like an explicitly defined class member would. For example imagine a struct called creature that has the properties/members creature.numberofhands, creature.fingersperhand and finally the property creature.totalfingers that automatically gets calculated from the above members.
Heres an example of the closest I got to what I wanted to achieve:
#include <iostream>
typedef struct creature {
int numberofhands;
int fingersperhand;
int totalfingers();
} creature;
int creature::totalfingers()
{
return numberofhands * fingersperhand;
};
int main()
{
creature human;
human.numberofhands = 2;
human.fingersperhand = 5;
printf("%d",human.totalfingers());
return(0);
}
What's really annoying me about this, is that I have to treat the calculated one DIFFERENTLY from the explicitly defined ones, i.e. I have to put "()" after it.
How can I change the code, so I can use: human.totalfingers without ever explicitly defining it?
The simplest option would be to use public member functions and make the actual properties hidden.
Something like this:
class Creature {
public:
Creature(int numhands, int fingersperhand) // constructor
: m_numhands{numhands}, m_fingersperhand{fingersperhand}
{ }
int fingersPerHand() const { return m_fingersperhand; }
int numberOfHands() const { return m_numhands; }
int totalFingers() const { return numberOfHands() * fingersPerHand(); }
private:
const int m_numhands;
const int m_fingersperhand;
};
The private member variables are an implementation detail. Users of the class just use the three public member functions to get the different number of fingers after construction and don't need to care that two of them are returning constant stored numbers and the third returns a calculated value - that's irrelevant to users.
An example of use:
#include <iostream>
int main()
{
Creature human{2, 5};
std::cout << "A human has "
<< human.totalFingers() << " fingers. "
<< human.fingersPerHand() << " on each of their "
<< human.numberOfHands() << " hands.\n";
return 0;
}
If - as per your comment - you don't want to use a constructor (although that's the safest way to ensure you don't forget to initialize a member), you can modify the class like this:
class CreatureV2 {
public:
int fingersPerHand() const { return m_fingersperhand; }
int numberOfHands() const { return m_numhands; }
int totalFingers() const { return numberOfHands() * fingersPerHand(); }
void setFingersPerHand(int num) { m_fingersperhand = num; }
void setNumberOfHands(int num) { m_numhands = num; }
private:
// Note: these are no longer `const` and I've given them default
// values matching a human, so if you do nothing you'll get
// human hands.
int m_numhands = 2;
int m_fingersperhand = 5;
};
Example of use of the modified class:
#include <iostream>
int main()
{
CreatureV2 human;
std::cout << "A human has "
<< human.totalFingers() << " fingers. "
<< human.fingersPerHand() << " on each of their "
<< human.numberOfHands() << " hands.\n";
CreatureV2 monster;
monster.setFingersPerHand(7);
monster.setNumberOfHands(5);
std::cout << "A monster has "
<< monster.totalFingers() << " fingers. "
<< monster.fingersPerHand() << " on each of their "
<< monster.numberOfHands() << " hands.\n";
CreatureV2 freak;
freak.setFingersPerHand(9);
// Note: I forgot to specify the number of hands, so a freak get
// the default 2.
std::cout << "A freak has "
<< freak.totalFingers() << " fingers. "
<< freak.fingersPerHand() << " on each of their "
<< freak.numberOfHands() << " hands.\n";
return 0;
}
Note: all of the above assumes you are using a modern C++14 compiler.
What you have described is one of the reasons why encapsulation and "member variables should be private" is the recommended way of doing things in C++.
If every variable is accessed through a function, then everything is consistent, and refactoring from a member variable to a computation is possible.
Some languages, like C# or D, have the concept of "properties", which provide a way around the issue, but C++ does not have such a construct.
For fun, the proxy way to avoid extra parenthesis, (but with some extra costs):
class RefMul
{
public:
RefMul(int& a, int& b) : a(a), b(b) {}
operator int() const { return a * b; }
private:
int& a;
int& b;
};
struct creature {
int numberofhands;
int fingersperhand;
RefMul totalfingers{numberofhands, fingersperhand};
};
Demo
Note: to use RefMul with printf, you have to cast to int:
printf("%d", int(human.totalfingers));
That cast would not be required if you use c++ way to print:
std::cout << human.totalfingers;
If you're after consistency, you can make your changes the other way around. Replace the two member variables with constant methods which simply return copies of the member variables. That way, the way you access data is consistent and you don't have to worry about some code changing the values of the member variables when it shouldn't.
Others have provided very good answers. If you are looking for consistency, probably the easiest way is to make use of member functions (as #Jesper Juhl has answered).
On the other hand, if you strictly want to use class members that are calculated automatically from other members, you can use properties. Properties (as are defined in C# and Groovy) are not a standard feature of C++ but there are ways to implement them in C++. This SO question has a very good overview of the ways that properties can be defined and used in C++. My favorite way of defining properties is taking advantage of Microsoft-specific extension for properties in Visual C++ (obviously, this approach is specific to Microsoft Visual C++). A documentation of properties in Visual C++ can be found in MSDN. Using properties in Visual C++, your code can be modified to:
struct creature {
int numberofhands; // use of public member variables are generally discouraged
int fingersperhand;
__declspec(property(get = get_totalfingers)) // Microsoft-specific
int totalfingers;
private:
int fingers;
int get_totalfingers()
{
return numberofhands * fingersperhand; // This is where the automatic calculation takes place.
}
};
This class can be used like this:
#include <iostream>
int main()
{
creature martian;
martian.numberofhands = 2;
martian.fingersperhand = 4; // Marvin the Martian had 4!
// This line will print 8
std::cout << "Total fingers: " << martian.totalfingers << std::endl;
return 0;
}
As I said earlier, properties are not a standard feature of C++ but there are ways to get them in C++ which either rely on smart tricks or using compiler-specific features. IMHO, using simple functions (as #Jesper Juhl described) is a better alternative.

initializing an passing a string array as a parameter

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.

Not able to use function variables ? Error expression must have class type

Hey i want to use the function wolves variable in the storyline and im trying to do this :
"\nYou awake on a beach to the sound of"<< Wolves().name; " starving and blood hungry,"
"\nThere is a Rock on the ground. You pick it up";
inventory.push_back("Rock");
But Wolves().name; there is an error as mentioned in the title. Why cant i do this?
Here is the code for the function Wolves:
void Wolves()
{
string name = "Wolves";
int health = 20;
hitPoints() +1;
}
You can't access variables defined in a function from outside the function in C++, but you can change it to a class:
class Wolves {
public:
string name;
// ...
Wolves(); // Constructor
//...
}
To access it you can use
Wolves wolve;
wolve.name = "whateverName"; // or set it in the constructor
cout << wolve.name << endl;
What you did in there is create local variables within the function. Once the function exits, they no longer exist. What you want to do is make a Wolves class and create public member variables to do what you want. For an example,
class Wolves {
public:
string name;
int health;
Wolves(string name, int a);
}
Then on the main function,
Wolves w("Bob", 20);
cout << "The name is: " << w.name << endl;
Will output "The name is: Bob"
void functions don't really do anything unless you pass the value in by reference. If you want to alter the object via void function, you should do something like
void Wolves(Wolves & wolfToChange)
{
wolfToChange.name = "Bob";
}
and that will directly alter the object.
You declared "name" as a local variable in a function called Wolves(), but the code that you were referring to expects the function Wolves() to return an object that has an accessible member name. That is why the compiler is complaining.
The way you wrote the code suggests that Wolves should be a class or struct, not a function.

C++ geting error while using function inside class

I can't figure out why I get this error: "the function was not declared". I am still a newbie at programming, but I am trying my best to learn it!
so here is my code, I would be realy greatful if you could help me:
main:
#include <iostream>
#include <vector>
#include "szovegkezelo.h"
using namespace std;
int main()
{
string sz;
beolvas(sz);
kiir(sz);
return 0;
}
header:
#ifndef SZOVEGKEZELO_H_INCLUDED
#define SZOVEGKEZELO_H_INCLUDED
#include <iostream>
using namespace std;
class szovegkezelo {
protected:
string sz;
public:szovegkezelo
void beolvas(string &sz);
void kiir(string t);
};
#endif // SZOVEGKEZELO_H_INCLUDED
cpp:
#include "szovegkezelo.h"
#include <iostream>
void szovegkezelo::beolvas(string &sz)
{
getline(cin, sz);
}
void szovegkezelo::kiir(string t)
{
cout << "a beadott szoveg: " << t << endl;
cout << "a string hossza: " << t.size() << endl;
}
From what it looks like, you are trying to call a classes function (method) called 'beolvas' from 'main' but because it belongs to a class, you can't call it like that, you need to create an instance of that class and call the method on that instance, or make the function static and call it from the class.
Your first option is to create an instance of the class and then call the methods on the class like so:
int main()
{
string sz;
szovegkezelo szov;
szov.beolvas(sz);
svoz.kiir(sz);
return 0;
}
Your second option is to make the functions in your class static, this way they will not need an instance of the class to be called:
int main()
{
string sz;
szov::beolvas(sz);
svoz::kiir(sz);
return 0;
}
static void szovegkezelo::beolvas(string &sz)
{
getline(cin, sz);
}
static void szovegkezelo::kiir(string t)
{
cout << "a beadott szoveg: " << t << endl;
cout << "a string hossza: " << t.size() << endl;
}
Been a while since I've done anything static in c++ so please correct me if I've done something wrong in the second option.
Your two or more data types... error comes from a misuse of...something...after that public access specifier.
Change this:
public:szovegkezelo
to this:
public:
If you're trying to make a constructor, it needs to be declared like any other function, minus the return type.
Your other error occurs because this function was declared improperly.
Other than that, you need to create an object before you can call the class's functions. Each object has it's own set of variables that the functions work on. I would seriously recommend reading a good beginner C++ OOP book.
Somewhere in main, you need to create an object:
szovegkezelo myObject;
Then, use it to call functions:
myObject.kiir (sz);
Finally, note that your data members should typically be declared with the private access specifier. protected has nothing to do with normal classes that are not inherited from.
couple of things :
1) In main you have not instantiated an object of szovegkezelo and you are trying to call beolvas . Compiler is looking for a free function beolvas whereas you have declared beolvas as member function
2) public:szovegkezelo is not right if you are looking for a default constrcutor that does nothing don't have that line else if you need to do something specific with default construct declare it as szovegkezelo() in header.
3) as mentioned in comments it is not a good practice to put
using namespace std in header files or any using namespace