I wish to create a constructor which takes input value from user, i.e value of a and b and then I wish to use these values in another function swap. This is more of general example. I wish to know where my concept is wrong.
#include <iostream>
using namespace std;
class swap_value
int a,b;
public:
swap_value()
{
cout<<"enter two numbers to swap";
cout<<"value of a is:";
cin>>a;
cout<<"value of b is:";
cin>>b;
}
void swap(int &a,int &b)
{
int temp=a;
a=b;
b=temp;
cout<<"value of a is :"<<a;
cout<<"value of b is :"<<b;
}
};
int main() {
swap_value obj;
obj.swap();
return 0;
}
#include <iostream>
using namespace std;
class swap_value {
int a,b;
public:
swap_value()
{
cout<<"enter two numbers to swap";
cout<<"value of a is:";
cin>>a;
cout<<"value of b is:";
cin>>b;
}
void swap(int &a,int &b)
{
int temp=a;
a=b;
b=temp;
cout<<"value of a is :"<<a;
cout<<"value of b is :"<<b;
}
};
int main() {
swap_value obj;
obj.swap();
return 0;
}
The thing that you should know is that all members of a class are accessible to all the methods of your class. So they don't need to be passed as parameters. The code you wrote doesn't compile (include error messages next time) because SwapValue doesn't have a method called swap() that takes no parameters.
Here is your code that does what you want it to. The change that I made was simply to make SwapValues::swap() take no parameters. Also, it is common practice to use UpperCamelCase for class names in C++. Indeed, it took me more time than it should have to notice that swap_values(){...} was your constructor for that reason.
#include <iostream>
using namespace std;
class SwapValues {
int a,b;
public:
SwapValues()
{
cout<<"enter two numbers to swap";
cout<<"value of a is:";
cin>>a;
cout<<"value of b is:";
cin>>b;
}
void swap()
{
int temp=a;
a=b;
b=temp;
cout<<"value of a is :"<<a << std::endl;
cout<<"value of b is :"<<b << std::endl;
}
};
int main() {
SwapValues sv;
sv.swap();
return 0;
}
Edit
To respond to the follow-up general question underlying the problem, the reason you are confused is because you are not sure about how the function gets access to a and b.
The short version is that methods of a class have built in access to all the attributes of the class.
The long version is that the instance of the class gets implicitly passed to methods of the class as an implicit parameter (called this in C++). So all functions of a class MyClass like
int MyClass::my_function( --parameters-- )
become
int MyClass::my_function(MyClass* this, --parameters--)
and the compiler, when it compiles code of such a function, sees
some_var = 1234;
will check firs if the function has a local variable or a local static variable or a parameter called some_var, and if there isn't, it will see if
this->some_var = 1234;
that is, it will check if `MyClass has an attribute called some_var.
In your case, in the working code we have
int temp = a;
so the compiler looks: is there a local variable called a, no local variable, is there a parameter called a, nope, next, what about this->a, the class does have an attribute called a so that's what we use.
So you always pass parameters, is the answer to your question but in the example of your function, that is done automatically. That's good because if you add an attribute to your class, you don't have to alter all the methods of your class to take an extra parameter, all the methods of the class will already have it.
In your first example, in fact, you should run this piece of code. It will show what I mean.
#include <iostream>
using namespace std;
class SwapValues {
public:
int a,b;
SwapValues()
{
a = 1;
b = 2;
}
void wrong_method(int &a, int &b)
{
std::cout << "wrong_method : "
<< "a = " << a
<< ", b = " << b
<< ", this->a = " << this->a
<< ", this->b = " << this->b << std::endl;
}
void right_method(int ¶m_1, int& param_2)
{
std::cout << "right_method : " << "a = " << a
<< ", b = " << b
<< ", param_1 = " << param_1
<< ", param_2 = " << param_2 << std::endl;
}
};
int main() {
SwapValues sv;
int c = 3;
int d = 4;
sv.wrong_method(c,d);
sv.right_method(c,d);
return 0;
}
Gives
wrong_method : a = 3, b = 4, this->a = 1, this->b = 2
right_method : a = 1, b = 2, param_1 = 3, param_2 = 4
This should demonstrate what I meant. The right and wrong because the wrong function has a name clash between the parameters and the attributes of the object. It makes errors possible and reflects bad design.
#include <iostream>
using namespace std;
class swap_value
{
private:
int a;
int b;
public:
swap_value()
{
cout<<"enter two numbers to swap";
cout<<"value of a is:";
cin>>a;
cout<<"value of b is:";
cin>>b;
}
void swap()
{
int temp=a;
a=b;
b=temp;
cout<<"value of a is :"<<a;
cout<<"value of b is :"<<b;
}
};
int main() {
swap_value obj;
obj.swap();
return 0;
}
Related
My aim with this program is to have a vector of objects describing various types of vehicles. The base class will have a user defined type variable, while each of the subclasses will have a default value as type(eg Van, Bus, etc.). After some searching I found that the best way to use both base and derived classes in a vector is to use a vector of pointers. Here is a simplified version of the code I wrote:
#include <iostream>
#include <string>
#include <vector>
#include <memory>
using namespace std;
class Vehicle
{
public:
Vehicle();
~Vehicle();
virtual void Initialize(string a,string b, int c, int d, int e, string f);
void print_details();
void get_yard(int x);
string type;
protected:
string make_and_model;
int max_pass;
int max_load;
int yard;
string date;
};
class Lorry : public Vehicle
{
public:
void Initialize(string a="Lorry", string b, int c, int d, int e, string f);
};
int i,count;
std::vector<std::unique_ptr<Vehicle>> arr;
Vehicle::Vehicle()
{
std::cout << "New Entry created." << std::endl;
}
Vehicle::~Vehicle()
{
std::cout << "Entry closed." << std::endl;
}
void Vehicle::Initialize(string a,string b, int c, int d, int e, string f)
{
type=a;
make_and_model=b;
max_pass=c;
max_load=d;
yard=e;
date=f;
}
void Lorry::Initialize(string a="Lorry", string b, int c, int d, int e, string f)
{
make_and_model=b;
max_pass=c;
max_load=d;
yard=e;
date=f;
}
void Vehicle::print_details()
{
std::cout << "Vehicle Type:"<< type << std::endl;
std::cout << "Make And Model:"<< make_and_model << std::endl;
std::cout << "Maximum Passengers:"<< max_pass << std::endl;
std::cout << "Maximum Load Capacity(in Kg):"<< max_load << std::endl;
std::cout << "Located Yard:"<< yard << std::endl;
std::cout << "Date of Arrival(dd-MM-YYYY):"<< date <<"\n"<< std::endl;
}
void new_objects()
{
std::cout<<"How many entries?"<<std::endl;
std::cin>>count;
std:: cout<<"The open yards are: Yard 1, Yard 2, Yard 3"<<std::endl;
for (i = 0; i < count; i++)
{
int vc_choice;
std::cout<<"What is the vehicle type?"<<std::endl;
std::cout<<"1.Lorry\n6.Other\n";
std::cin>>vc_choice;
string a;
string b;
int c;
int d;
int e;
string f;
switch (vc_choice)
{
case 1:
arr.emplace_back(new Lorry());
std::cout<<"Enter the vehicle make and model: "<<std::endl;
std::cout << "WARNING: Do NOT use spaces, use underscores." << std::endl;
std::cin>>b;
std::cin.clear();
std::cout<<"Enter the maximum passenger capacity: "<< std::endl;
std::cin>>c;
std::cin.clear();
std::cout<<"Enter the maximum load capacity(Kgs): "<<std::endl;
std::cin>>d;
std::cout<<"Enter the yard number"<<std::endl;
std::cin>>e;
std::cout<<"Enter the date of arrival(dd-mm-yyyy): "<<std::endl;
std::cin>>f;
arr.Initialize(a,b,c,d,e,f);
break;
default:
arr.emplace_back(new Vehicle());
std::cout<<"Enter the vehicle type: "<<std::endl;
std::cout << "WARNING: Do NOT use spaces, use underscores." << std::endl;
std::cin>>a;
std::cout<<"Enter the vehicle make and model: "<<std::endl;
std::cout << "WARNING: Do NOT use spaces, use underscores." << std::endl;
std::cin>>b;
std::cin.clear();
std::cout<<"Enter the maximum passenger capacity: "<< std::endl;
std::cin>>c;
std::cin.clear();
std::cout<<"Enter the maximum load capacity(Kgs): "<<std::endl;
std::cin>>d;
std::cout<<"Enter the yard number"<<std::endl;
std::cin>>e;
std::cout<<"Enter the date of arrival(dd-mm-yyyy): "<<std::endl;
std::cin>>f;
arr.Initialize(a,b,c,d,e,f));
break;
}
}
}
void print_all()
{
for (int a= 0; a<5; i++)
{
arr[a].print_details();
}
}
int main()
{
new_objects();
print_all();
return 0;
}
Trying to compile it I get this error:
[test unique_ptr.cpp 2021-04-24 06:59:33.521]
,,test unique_ptr.cpp: In function 'void new_objects()':
test unique_ptr.cpp:122:29: error: 'class std::vector<std::unique_ptr<Vehicle> >' has no member named
'Initialize'
122 | arr.Initialize(a,b,c,d,e,f);
| ^~~~~~~~~~
test unique_ptr.cpp:151:29: error: 'class std::vector<std::unique_ptr<Vehicle> >' has no member named
'Initialize'
151 | arr.Initialize(a,b,c,d,e,f));
| ^~~~~~~~~~
test unique_ptr.cpp: In function 'void print_all()':
test unique_ptr.cpp:162:16: error: '__gnu_cxx::__alloc_traits<std::allocator<std::unique_ptr<Vehicle> >,
std::unique_ptr<Vehicle> >::value_type' {aka 'class std::unique_ptr<Vehicle>'} has no member named
'print_details'
162 | arr[a].print_details();
| ^~~~~~~~~~~~~
I've tried using the arrow operator but this still doesn't work, as arr is not a pointer. How can I get the program to run?
Three types of errors.
You can't use default value for the 1st argument and leaving the rest alone. Meaning you cannot write void Initialize(string a="Lorry", string b, int c, int d, int e, string f);. You can write:
void Initialize(string a, string b, int c, int d, int e, string f)
or
void Initialize(string a, string b, int c, int d, int e, string f="Lorry")
or
void Initialize(string a, string b, int c, int d, int e = 0, string f="Lorry")
& the second one is you can't use . to access the method from a pointer, instead you need to use ->. read the thread. The third one is you are calling Initialize from a vector. You need to specify the index to indicate its element. You need to write:
arr[arr.size() - 1]->Initialize(a, b, c, d, e, f);
......
arr[a]->print_details();
My program deals with accessing attributes of a structure which is defined inside a class. When I use a pointer of type struct to show the structure's attributes, it is throwing a segmentation fault and stops the execution. Though it is printing the structure's attributes fine if I just use a variable of type struct. I tried debugging the code with gdb and it is showing the segmentation fault occurs at line 27 which is poly.params->a = 1;. Why can't we use pointers in this case or am I making a stupid mistake? Here is the sample of the code:
#include <iostream>
using namespace std;
class QuadraticFunc
{
public:
QuadraticFunc(){};
struct Coeff
{
double a;
double b;
double c;
} * params;
void ParamShow(const Coeff *params)
{
cout << "a: " << params->a << endl;
cout << "b: " << params->b << endl;
cout << "c: " << params->c << endl;
}
~QuadraticFunc(){};
};
int main()
{
QuadraticFunc poly;
poly.params->a = 1;
poly.params->b = 2;
poly.params->c = 1;
QuadraticFunc *polyPtr;
polyPtr = &poly;
cout << "The parameters for the first object: " << endl;
polyPtr->ParamShow(poly.params);
}
poly.params->a = 1;
params has not been initialized.
Replace
struct Coeff
{
double a;
double b;
double c;
} * params;
with
struct Coeff
{
double a;
double b;
double c;
} params;
And then replace each params-> with params.
Why can't we use pointers in this case or am I making a stupid mistake?
Yes, you are.
QuadraticFunc poly; // Your constructor leaves poly.params uninitialized
poly.params->a = 1; // Dereferencing uninitialized pointer invokes undefined behavior.
How should I fix this?
The best solution is to avoid the pointer here:
class QuadraticFunc
{
public:
QuadraticFunc(){};
struct Coeff
{
double a;
double b;
double c;
} params;
...
};
int main()
{
QuadraticFunc poly;
poly.params.a = 1;
...
polyPtr->ParamShow(&poly.params);
}
You may have a legitimate reason to have params as a pointer, but you have not yet shown what that reason may be.
In the code below, why can I call printAlternativ but not print?
To my understanding, the object should be removed and neither should work.
using namespace std;
class MemTest
{
public:
MemTest(string);
~MemTest();
void print();
void printAlternative();
string name;
};
void MemTest::print() {
cout << "Print: " << name << "\n";
}
void MemTest::printAlternative() {
cout << "Print Alternative\n";
}
MemTest::MemTest(string n) {
cout << "Constructor\n";
name = n;
}
MemTest::~MemTest() {
cout << "Destructor\n";
}
void call(MemTest *b) {
MemTest a("TestName");
a.print();
b = &a;
}
int main()
{
MemTest *b = NULL;
call(b);
b->print(); // This crashes
// b->printAlternative(); This works
return 0;
}
After call() object get destructed, so now object b does not have any reference of any object and you are trying to access "name" data member of object because of that it get crashed.
You can verify it by adding a cout<<"Test line"; after call(b); line in main()
And why other one is working because member functions are associated with class and get assigned when first time we declare object and compiler only swipe data member in destructor()
I'm trying to write a program that would print all palindrome in range [a, b]. I've written this so far, but nothing is printed after I input the values for a, b. What is missing?
#include "stdafx.h"
#include <iostream>
using namespace std;
int t = 0, rmd, z, a, b;
int reverse() {
while (z != 0) {
rmd = z% 10;
t = t * 10 + rmd;
z/= 10;
}
return t;
}
int palin() {
if (a == reverse()) {
return 1;
}
else
return 0;
}
int main() {
cout << "a: "; cin >> a;
cout << "b: "; cin >> b;
while (a <= b) {
z = a;
if (palin())
cout << a << endl;
a++;
}
system("pause");
return 0;
}
The problem is that the variable t is not local to your reverse() function. Its value survives to the following invocation, so the result of reverse becomes junk unrelated to the actual call.
You need to make t local to reverse() in order to fix this problem.
In general, it is a good idea to develop a habit of declaring your variables in the innermost scope to which they could belong without breaking your code. In this case, this would be the scope of reverse() function for t, and the scope of main for the remaining variables; palin should take a as its parameter.
Your use of variables is what is confusing you. The actual issue is not setting t to zero every time you call reverse, but you should think about how you use variable scoping and what functions actually do. Right now you have 2 procedures, that perform actions on global data. Instead try to formulate the problem using functions that accept arguments, and return a result.
#include <iostream>
using namespace std;
int reverse(int z) {
int t = 0;
int rmd;
while (z != 0) {
rmd = z % 10;
t = t * 10 + rmd;
z/= 10;
}
return t;
}
int palin(int z) {
return z == reverse(z);
}
int main() {
int a, b;
cout << "a: "; cin >> a;
cout << "b: "; cin >> b;
while (a <= b) {
if (palin(a)) {
cout << a << endl;
}
a++;
}
system("pause");
return 0;
}
I'm having some problems with my program which I do not understand.
On line 72, I get the error: "error C4700: uninitialized local variable 'sumInEuros' used" however surely it is initialized as I am using it to store a calculation?
Also on line 66 I get "error C4716: 'showPriceInEuros': must return a value" - why must this return a value? the function is simply meant to output a message to the console.
I'm using VS13 and it's c++.
Any help would be very much appreciated, because I am stuck!
Thanks!
#include <iostream> //for cin >> and cout <<
#include <cassert> //for assert
#include <iomanip> //for endl
#include <Windows.h>
using namespace std;
void processAPrice();
int getPriceInPounds();
int convertPriceIntoEuros(int pounds);
int showPriceInEuros(int pounds, int euros);
int calculateSum(int euros);
void produceFinalData(int sum, int numberOfPrices);
int main()
{
char answer('Y');
int numberOfPrices(0);
while (answer = 'Y')
{
processAPrice();
numberOfPrices++;
cout << "Continue? (Y/N)";
cin >> answer;
}
if (numberOfPrices > 0)
//produceFinalData(sum, numberOfPrices);
system("PAUSE"); //hold the screen until a key is pressed
return(0);
}
void processAPrice() //
{
int pounds = getPriceInPounds();
int euros = convertPriceIntoEuros(pounds);
int sum = showPriceInEuros(pounds, euros);
calculateSum(euros);
}
int getPriceInPounds() //
{
int priceInPounds;
cout << "Enter a price (in Pounds): /234";
cin >> priceInPounds;
return priceInPounds;
}
int convertPriceIntoEuros(int priceInPounds) //
{
const int conversionRate(0.82);
return priceInPounds / conversionRate;
}
int showPriceInEuros(int pounds, int euros) //
{
SetConsoleOutputCP(1252);
cout << "The Euro value of /234" << pounds << "is: \u20AC" << euros;
}
int calculateSum(int euros) //
{
int sumInEuros;
sumInEuros = (sumInEuros + euros);
return sumInEuros;
}
void produceFinalData(int sum, int numberOfPrices) //
{
SetConsoleOutputCP(1252);
cout << "The total sum is: \u20AC" << sum;
cout << "The average is: \u20AC" << (sum/numberOfPrices);
}
Well, the showPriceInEuros function is not returning the int it promises to return in its signature. That's the error.
If the function is not supposed to return a value, you should declare its return type as void:
void showPriceInEuros(int pounds, int euros);
//^^
and then:
void showPriceInEuros(int pounds, int euros) {
SetConsoleOutputCP(1252);
cout << "The Euro value of /234" << pounds << "is: \u20AC" << euros;
}
of course.
surely it is initialized as I am using it to store a calculation?
The calculation is based on the variable's uninitialised value:
sumInEuros = (sumInEuros + euros);
^^^^^^^^^^ not initialised
Perhaps you could declare it static, so that its value is preserved between calls to the function, in order to calculate the sum of all the values you pass to the function. Usually, it would be better to use a class to manage persistent data like this, with member functions to update and access it.
why must this return a value?
Because you say it does:
int showPriceInEuros(int pounds, int euros)
^^^
If it shouldn't return a value, change the return type to void.
You do not initialize sumInEuros in this function. You store a result in it - that's true but to calculate the result you are using the uninitialized value.
int calculateSum(int euros) //
{
int sumInEuros;
sumInEuros = (sumInEuros + euros);
return sumInEuros;
}
Answering the question from below:
I would probably create a class PriceCalculator which has all the functions of your algorithm plus the internal state:
class PriceCalculator {
int m_sumInEuros;
public:
PriceCalculator()
: m_sumInEuros(0) { }
void processAPrice(int price);
int getSumInEuros() const { return m_sumInEuros; }
private:
void updateSum(int priceInEuros);
};
From your main function you should create an object of this type and give it the prices you want to sum. Do not do any console input from your class.
int main()
{
PriceCalculator calc;
char answer('Y');
int numberOfPrices(0);
while (answer = 'Y')
{
int priceInPounds;
cout << "Enter a price (in Pounds): /234";
cin >> priceInPounds;
calc.processAPrice(priceInPounds);
numberOfPrices++;
cout << "Continue? (Y/N)";
cin >> answer;
}
...
You might want to think about adding the numberOfPrices to your calculator class as well. At the end you will do all the operations in your class but the user input and console output outside your class. Your class can be tested automatically this way and is completely independent from the user interface.