I've been searching everywhere but I can't find a solution, though it's probably a simple one since I'm just starting out. Basically, I'm trying to pass in two values through a constructor, but the values I'm passing in aren't correct either when running or debugging.
Transaction.h
#include <string>
class Transaction {
private:
int amount;
std::string type;
public:
Transaction(int amt, std::string kind);
std::string Report() const;
// ...irrelevant code...
};
Transaction.cpp
#include "Transaction.h"
using namespace std;
Transaction::Transaction(int amt, std::string kind) { };
string Transaction::Report() const {
string report;
report += " ";
report += type; // supposed to concat "Deposit" to string
report += " ";
report += to_string(amount); // supposed to concat amount to string
return report;
// This doesn't return the word "Deposit", nor does
// it return the correct amount. I don't think that
// this is adding "Deposit" to 50, because the values
// change every time I run the program.
}
Parameters.cpp
#include "Transaction.h"
#include <iostream>
using namespace std;
// ...irrelevant code...
int main() {
int money = 50;
cout << "Depositing $" << money << endl;
Transaction deposit(money, "Deposit");
// For some reason, this doesn't pass in int money.
cout << "Original: " << deposit.Report() << endl;
// And this cout prints some large value instead of 50.
// ...irrelevant code...
}
No matter what I do, the value changes. Some output I get:
Depositing $50
Original: 13961048
After pass by value: 13961048
After pass by reference: 27922096
Depositing $50
Original: 11208536
After pass by value: 11208536
After pass by reference: 22417072
Depositing $50
Original: 14092120
After pass by value: 14092120
After pass by reference: 28184240
Any help to point me in the right direction (or just a straight answer) would be great!
The values are being passed to the constructor, alright. The problem is just that you're not doing anything with them!
Look at the implementation for the constructor:
Transaction::Transaction(int amt, std::string kind) { };
This doesn't do anything. In particular, it doesn't save (store) the values of the parameters that were passed.
You probably want this:
Transaction::Transaction(int amt, std::string kind)
: amount(amt)
, type(kind)
{ }
The weird colon syntax is called a member initialization list, and does just what it sounds like.
Note that you should have been able to see this in the debugger. What you'd do is set a breakpoint on the definition of the constructor, and then check to see what the values of the parameters were. You'd see that they were being passed correctly (and that the values were not "wrong"). Then you'd have to figure out why they weren't getting saved, and you could have seen that pretty easily by single-stepping through the code from that point forward.
You don't pass the copy the value of the arguments in the class variables
here the correct contructor code :
Transaction::Transaction(int amt, std::string kind) {
this->amount=amt; //copy the value of amt to Transaction.amount
this->type=kind; //copy the value of kind to Transaction.kind
};
Related
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.
I am a C++ novice and have an assignment using Oldie McOldSchool arrays and pointers. I have looked at this specific problem for about 8-12 cumulative hours now, kind of want to shove my face into a brick wall and don't really know what to think at this point. I am hoping from help from the experts here at SO!
I have the following class
#include <iostream>
#include <string>
using namespace std;
#include "mainclass.h"
#include "mysubobject1.h"
const string dataString[] =
{
"stringvalue,stringvalue,stringvalue,stringvalue,19,51,36,41,STUFF1",
"stringvalue,stringvalue,stringvalue,stringvalue,19,52,37,44,STUFF2",
"stringvalue,stringvalue,stringvalue,stringvalue,19,53,38,46,STUFF3",
"stringvalue,stringvalue,stringvalue,stringvalue,19,54,39,49,STUFF1",
"stringvalue,stringvalue,stringvalue,stringvalue,19,55,30,38,STUFF2",
};
MyObject* myObjectArray[5];
const string* dataArray[5];
int delimiterPositionArray[5][9];
string tokenArray[5][9];
Stuff stuff;
void main()
{
MainClass* mainClass = new MainClass();
dataArray[0] = &dataString[0];
dataArray[1] = &dataString[1];
dataArray[2] = &dataString[2];
dataArray[3] = &dataString[3];
dataArray[4] = &dataString[4];
/*Parse the contents of string into Token array. I have this working and can share if necessary but trimmed it out to keep this easy to look at */
for (int i = 0; i < 5; i++)
{
/* Logic to set the value of stuff goes here - it's very simple and trimmed for ease of reading */
mainClass->add(tokenArray[i][0], tokenArray[i][1], tokenArray[i][2], tokenArray[i][3], stoi(tokenArray[i][4]), stoi(tokenArray[i][5]), stoi(tokenArray[i][6]), stoi(tokenArray[i][7]), stuff);
}
cout << "TEST" << endl;
cout << mainClass->myObjectArray[0] << endl;
}
void MainClass::add(string string1, string string2, string string3, string string4, int int1, int int2, int int3, int int4, Stuff stuff)
{
MyObject myObject;
if (stuff == STUFF2) {
MySubObject1 myObject;
myObject.SetStuff(stuff);
}
myObject.SetString1(string1);
myObject.SetString2(string2);
myObject.SetString3(string3);
myObject.SetString4(string4);
myObject.SetInt1(int1);
int* intArray[] = { &int2, &int3, &int4 };
myObject.SetIntArray(intArray);
//Awful temporary array filling logic (which doent work properly, but works for the purpose of testing this problem)
if (myObjectArray[0] == nullptr)
{
myObjectArray[0] = &myObject;
}
else
{
if (myObjectArray[1] == nullptr)
{
myObjectArray[1] = &myObject;
}
/* ….until the array is filled */ }
}
And the question:
When I inspect this line of code from the main method in the mainclass.cpp in the VB debugger, all looks perfect. Token array contains what I expect:
mainClass->add(tokenArray[i][0], tokenArray[i][1], tokenArray[i][2], tokenArray[i][3], stoi(tokenArray[i][4]), stoi(tokenArray[i][5]), stoi(tokenArray[i][6]), stoi(tokenArray[i][7]), stuff);
I keep stepping through the code and get through the end of the add method. I see that everything looks fine by the time I reach the end of the add method. The strings and integers all appear to get set perfectly. I inspect the following line after the debugger runs over it and see everything looks great. Each array field has the data I expect in it. (the logic sucks and the data is the same for each array index, but that is for a later troubleshooting session :D)
myObjectArray[0] = &myObject;
After the add method runs, execution is deferred back to the main method and the following code outputs the results to the screen:
cout << "TEST" << endl;
cout << mainClass->myObjectArray[0] << endl;
This is where the problem is.... mainClass->myObjectArray[0] has empty values in all string properties and nothing is outputted for them (they contain "").... but the int properties have the proper output for some reason!
If anyone would have any insight into why the ints are available and the strings don't appear to be, I would be eternally grateful!
Thanks again!
Given you really didn't post all of your code, the code you did post shows one major issue, and could be the reason why your program behaves as it does.
In your MainClass::add() function, you're storing the addresses of local variables in the MainClass::myObjectArray array, and attempting to access these addresses from outside the add() function.
A synopsis of the code:
int main()
{
MainClass* mainClass = new MainClass();
//...
mainClass->add(...);
//...
cout << mainClass->myObjectArray[0] << endl; // <-- index 0 points to a garbage value
}
void MainClass::add(string string1, string string2, string string3, string string4, int int1, int int2, int int3, int int4, Stuff stuff)
{
MyObject myObject;
if (stuff == STUFF2) {
MySubObject1 myObject; // <-- Local variable
//...
int* intArray[] = { &int2, &int3, &int4 }; // <-- Another local variable
//...
myObject.SetIntArray(intArray); // <-- Storing address of local
//...
myObjectArray[0] = &myObject; // <-- Storing address of local
//...
}
When add() returns, those addresses will not be pointing to valid variables, since those variables no longer are valid since they are local variables.
So the fix is that you have to ensure that whatever pointers you place in your myObjectArray array, the lifetimes (scope) of those variables that are pointed to will last as long as myObjectArray.
A better solution to use an array of a type that stores "any" value such as an array of std::any.
In addition to this, you should attempt to reduce the unnecessary calls to new. For example, your main function starts off on the wrong foot:
int main()
{
MainClass* mainClass = new MainClass();
This could have simply been:
int main()
{
MainClass mainClass;
Scenario
I am in the process of learning C++, so please forgive my naivety. I have attempted to build my own class, objects and methods - each of which seem to work as expected. However I am running into issues with what seems to be uninitialized storage (and possibly the use of local objects?) however I would like to know how to fix it, if indeed it is meant to be, or an alternative. My current train of thought is that the object needs to be passed...however that could be way off...
Code
//header
class Car{
public:
USHORT GetMin();
void SetMin(USHORT min);
private:
USHORT itsMinPrice;
};
USHORT Car::GetMin(){
return itsMinPrice;
}
void Car::SetMin(USHORT min){
itsMinPrice = min;
}
-
void StartingPrices(){
Car Mercedes;
std::cout << Mercedes.GetMin() << "\n";
Mercedes.SetMin(50);
std::cout << Mercedes.GetMin()<< "\n";
}
int main(){
float input;
Car Mercedes;
Mercedes.SetMin(100);
StartingPrices();
std::cout << Mercedes.GetMin() << "\n";
std::cin >> input;
return 0;
}
Expected output
100, 50, 50
Actual output
debug win32 - 52428, 50, 100
release win32 - 0, 50, 100
In your StartingPrices function, the Mercedes object you call GetMin is created on the line before, i.e., not the same object as the one you create in the main function.
That means that the object do not yet have itsMinPrice set to anything, hence the value will be garbage (that is, a value which you don't really have control over), in this case 52428 in debug and 0 in release.
What I think you wish to do is pass a reference of the Mercedes object from the main function into the StartingPrices function:
void StartingPrices(Car& mercedes){
std::cout << Mercedes.GetMin() << "\n"; // Here the GetMin method will return 100.
...
}
int main(){
....
Car Mercedes;
Mercedes.SetMin(100);
StartingPrices(Mercedes);
....
}
Its also a good idea to set the default value of the members in the constructor of the class.
In your Car class you do not initialize your member variable itsMinPrice except when you call SetMin, this means there is a risk that you will use an uninitialized Car instance if you forget to call SetMin on it. Normally it is good to have initialization in a constructor of the class with some value e.g.
Car() : itsMinPrice(0) {
}
or create a constructor that takes an initial value
Car(USHORT minValue) : itsMinPrice(minValue) {
}
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.
#include<iostream>
#include <string>
using namespace std;
class Car{
private:
public: Car(int, string, int);
Car(){} //default constructor
void setbrake();
void setacc();
int year,speed;
string make;
};
Car::Car(int year, string make, int speed = 0) //constructor with parameters
{
cout << "Enter your car's year." << endl;
cin >> year;
cout << "Enter your car's make. " << endl;
cin >> make;
cin.ignore();
speed = 0; }
void Car::setbrake(){ //first function
speed = speed - 5;
cout << "Your " << make << " is traveling at " << speed;
cout << " MPH.";}
void Car::setacc(){ //second function
speed = speed + 5;
cout << "Your " << make << " is traveling at " << speed;
cout << " MPH.";}
int main()
{
Car car1(0,"s");
cout << car1.make;
cout << car1.speed;
cout << car1.year;
car1.setacc();
system("pause");
return 0;
}
I'm having a problem getting my variables to display in my two member functions, and it doesn't display anything in main.
The speed variable always comes out to 49898575 <-- some randomly high number like that, and I assume I initialized it to 0.
I've been stuck on this all week.
How do I connect my class private variables and my member functions.
I thought my constructor with parameters would take care of that problem, but obviously not.
Can someone please take the time to critique this code for me. I'm going to pull my hair out.
Here's the problem that was assigned for class, and this is what I'm aiming to do, but I'm not catching on to classes and member functions, and how they work together.
Write a class named Car that has the following member variables:
• year. An int that holds the car’s model year.
• make. A string that holds the make of the car.
• speed. An int that holds the car’s current speed.
In addition, the class should have the following member functions.
• Constructor. The constructor should accept the car’s year and make as arguments
and assign these values to the object’s year and make member variables. The constructor
should initialize the speed member variable to 0.
• Accessors. Appropriate accessor functions should be created to allow values to be
retrieved from an object’s year, make, and speed member variables.
• accelerate. The accelerate function should add 5 to the speed member variable
each time it is called.
• brake. The brake function should subtract 5 from the speed member variable each
time it is called.
Demonstrate the class in a program that creates a Car object, and then calls the accelerate
function five times. After each call to the accelerate function, get the current speed of the car and display it.
Then, call the brake function five times.
After each call to the brake
function, get the current speed of the car and display it.
You're changing the values of your parameters, which shadow your members, leaving both ints uninitialized (the string will be an empty string).
The better option is to use different names:
Car::Car(int y, string m, int s = 0)
You could, however, use this:
this->speed = 0;
I'd recommend a constructor initializer list, though, which doesn't require either, and doing it in the order they're declared in the class:
Car::Car(int year, string make, int speed = 0)
: year(year), speed(speed), make(make) {}
Ideally, I would do something like this, with tweaking depending on what else it's meant to be used for (I'll keep it C++03):
class Car {
int year_;
std::string make_;
int speed_;
public:
Car(int, const std::string &, int);
void brake();
void accelerate();
void printInfo() const;
};
Car::Car(int year, const std::string &make)
: year_(year), make_(make), speed_() {} //speed should always be 0
void Car::brake() {
speed_ -= 5; //consider ensuring it stays at or above 0
}
void Car::accelerate() {
speed_ += 5;
}
void Car::printInfo() const {
std::cout << "Your " << make_ << " is traveling at " << speed_ << " MPH.";
}
You'll have to figure out exactly what the default constructor should do if you want one. I used a constructor initializer list to initialize the data members, I separated the printing from the accelerating/braking, accepted const references where reasonable, and made the printing function const since it doesn't modify the object.