error: invalid use of non-static member function C++ - c++

I have two classes that I want to chain-call (main -> execute -> calculate). However, the issue is that when I use:
&calculate::addition;
Addition will not be called even if the compiler doesn't return any error. If I try to remove the reference to
calculate::addition;
The compiler returns error
error: invalid use of non-static member function ‘void calculate::addition(double&, double, double)’
case 'a' : *calculate::addition; break;
^~~~~~~~
Tried using static before void with the same result as using reference.
#include <iostream>
class execute{
public:
void exec(char);
}jalan;
class calculate {
public:
void addition(double&, double, double);
void substraction(double&, double, double);
void multiply(double&, double, double);
void division(double&, double, double);
};
int main(void){
static double a, b;
static double result;
std::cout << "Type a, b, c, or d" << std::endl;
std::cout << "a. Addition\nb. Substraction\nc. Multiply\nd. Division" << std::endl;
std::cout << "Your Input: ";
static char option;
option = getchar();
std::cout << "First value: ";
std::cin >> a;
std::cout << "Next value: ";
std::cin >> b;
jalan.exec(option);
std::cout << result << std::endl;
return 0;
}
void execute::exec (char option){
switch(option){
case 'a' : &calculate::addition; break;
case 'b' : &calculate::substraction; break;
case 'c' : &calculate::multiply; break;
case 'd' : &calculate::division; break;
}
}
void calculate::addition(double& result, double a, double b){
result = a+b;
}
void calculate::substraction(double& result, double a, double b){
result = a-b;
}
void calculate::multiply(double& result, double a, double b){
result = a*b;
}
void calculate::division(double& result, double a, double b){
result = a/b;
}

You have several issues in your code. Lets start:
error: invalid use of non-static member function ‘void calculate::addition(double&, double, double)’
case 'a' : *calculate::addition; break;
This means you have to create an instance of calculate or mark the method with static like static void addition(double&, double, double);
So change your class to
class calculate {
public:
static void addition(double&, double, double);
static void substraction(double&, double, double);
static void multiply(double&, double, double);
static void division(double&, double, double);
};
The next issue is that in your switch statement you only create pointers to functions
void execute::exec (char option){
switch(option){
case 'a' : &calculate::addition; break;
case 'b' : &calculate::substraction; break;
case 'c' : &calculate::multiply; break;
case 'd' : &calculate::division; break;
}
}
This never executes a function, but only creates a function pointer which is discarded right away.
In order to get your code to work, consider this code (note the comments in the code, which explain changes needed):
#include <iostream>
class execute
{
public:
void exec(char, double&, double, double);
}jalan;
class calculate {
public: // added static keyword so you do not need to create a class instance
static void addition(double&, double, double);
static void substraction(double&, double, double);
static void multiply(double&, double, double);
static void division(double&, double, double);
};
int main(void){
static double a, b;
static double result;
std::cout << "Type a, b, c, or d" << std::endl;
std::cout << "a. Addition\nb. Subtraction\nc. Multiply\nd. Division" << std::endl;
std::cout << "Your Input: ";
static char option;
option = getchar();
std::cout << "First value: ";
std::cin >> a;
std::cout << "Next value: ";
std::cin >> b;
jalan.exec(option, result, a, b); // you need to pass the arguments which you want to use and modify
std::cout << result << std::endl;
return 0;
}
void execute::exec (char option, double& res, double a, double b){
switch(option){ // changed the function pointers to actual calls to the functions
case 'a' : calculate::addition(res, a, b); break;
case 'b' : calculate::substraction(res, a, b); break;
case 'c' : calculate::multiply(res, a, b); break;
case 'd' : calculate::division(res, a, b); break;
}
}
void calculate::addition(double& result, double a, double b){
result = a+b;
}
void calculate::substraction(double& result, double a, double b){
result = a-b;
}
void calculate::multiply(double& result, double a, double b){
result = a*b;
}
void calculate::division(double& result, double a, double b){
result = a/b;
}
Hope this helps understanding your problems.

To call any method in class calculate you have to declare a variable first then call the method for example:
calculate c;
double a,b,res;
c.addition(a,b,res);
or you define the methods as static functions, in that case the calling will be like that
calculate::addition(a,b,res);

Related

Error using unique_ptr to access functions in subclasses

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();

Trying to get my head around OOP and wondering if my functions are done correctly

I am making a simple little calculator application and I am wondering how best I can incorporate encapsulation and abstraction into my code to make it neat and organised.
Is this an ideal way on how to approach these methods with the following code? I am not sure if it is going a bit overboard but in my eyes it makes it very readable and tidy.
Also is there a rule in saying that if you are repeating code, it belongs in a function?
Thank you in advance.
// Test ApplicationV2.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <string>
#include <vector>
int getNumber();
char getOperation();
int additionResult(int& val1, int& val2);
int multiplyResult(int& val1, int& val2);
int divisionResult(int& val1, int& val2);
int main()
{
int val1, val2;
char operation;
std::cout << "Enter the first value.";
val1 = getNumber();
std::cout << "Enter operation";
operation = getOperation();
std::cout << "Enter second number.";
val2 = getNumber();
switch (operation)
{
case '+':
std::cout << additionResult(val1, val2);
break;
case '*':
std::cout << multiplyResult(val1, val2);
break;
case '/':
std::cout << divisionResult(val1, val2);
break;
default:
std::cout << "Please enter sufficient data.";
}
//Keep window open
std::string barn;
std::cin >> barn;
return 0;
}
int getNumber()
{
int x;
std::cin >> x;
return x;
}
char getOperation()
{
char op;
std::cin >> op;
return op;
}
int additionResult(int& val1, int& val2)
{
return (val1 + val2);
}
int multiplyResult(int& val1, int& val2)
{
return (val1 * val2);
}
int divisionResult(int& val1, int& val2)
{
return (val1 / val2);
}
As presented, your program doesn't use OOP (except in as much as std::cout and std::cin are objects). If you're aim is to explore using OOP as a way to structure the code, then consider:
#include <iostream>
class Calculation
{
public:
Calculation(int first, int second)
: first_(first), second_(second)
{ }
int add() { return first_ + second_; }
int multiply() { return first_ * second_; }
int divide() { return first_ / second_; }
private:
int first_, second_;
};
int main()
{
int val1, val2;
char operation;
if (std::cout << "Enter the first value: " &&
std::cin >> val1 &&
std::cout << "Enter operation: " &&
std::cin >> operation &&
std::cout << "Enter the second value: " &&
std::cin >> val2)
{
Calculation calc(val1, val2);
switch (operation)
{
case '+':
std::cout << calc.add() << '\n';
break;
case '*':
std::cout << calc.multiply() << '\n';
break;
case '/':
std::cout << calc.divide() << '\n';
break;
default:
std::cerr << "Invalid operator: must be +, * or /.\n";
}
}
else
std::cerr << "Error getting inputs.\n";
//Keep window open
std::cin.get(); // real operating systems don't need this ;-P
}
Note that the Calculation class is the OOP aspect, and it has private data: that's encapsulation. It doesn't abstract much though - problem's too simple - but you could say it's captured the inputs at construction and the add(), multiply(), divide() calls don't have to be aware of the type or quantity of data involved (i.e. Calculator might have stored a std::vector<int> or a double and the switch statement's code need not change, provided there's an operator<< overload for the return type of those three functions).
You could get a bit more abstraction by having a member function in Calculation like:
int do_operation(char c) const
{
switch (c)
{
case '+': return first_ + second_;
case '*': return first_ * second_;
case '/': return first_ / second_;
default: throw std::runtime_error("invalid operator character");
}
}
Then the use from main can just try an operation and see if it's supported, without knowing the exact operations provided by Calculation:
Calculation calc(val1, val2);
try
{
std::cout << calc.do_operation(operation) << '\n';
}
catch (const std::exception& e)
{
std::cerr << "oops - caught exception: " << e.what() << '\n';
}
This might not seem a big deal, but it means if you've got lots of places using the Calculation objects, you don't have to update them all when you want to support another operation. A disadvantage is that the return type of do_operation has to be the same for all the types of operation, so you can't decide "hey, I'll have divide return a double instead of rounding down to an int" and simply change divide()'s return type alone (but you could have them all return double - won't do much harm in this simple case, and more generally you can use "variant"s to return any of a set of types, but they're harder for the client code to use).
Also is there a rule in saying that if you are repeating code, it belongs in a function?
Pretty much. Do note that you weren't repeating (calling twice) any of the code you put into functions, but it gets important in more complex programs.
As an example of factoring the above code using a function, consider how the prompting and input could be combined in a reusable function:
template <typename T>
bool input(const std::string& prompt, T& value)
{
return std::cout << prompt && std::cin >> value;
}
The template <typename T> thing means the above function can work with any type of value. Using this input function, the prompting and input operations can be rewritten as:
if (input("Enter the first value: ", val1) &&
input("Enter operation: ", operation) &&
input("Enter the second value: ", val2))
{
Whether that's better depends on whether the reader can guess at what input does well enough not to need to go study the input function, but the more often it gets reused the more likely even such an effort would be worthwhile.
One possibility would be to have an abstract "binary operation" class, and then have derived classes for each of your actual operations (addition, subtraction, multiplication, division).
If you do this, you can then (for one example) create a container of (pointers or references to) binary operation objects, and look up the correct operation in that collection. For example:
struct bin_op {
virtual int operator()(int a, int b);
};
struct add : bin_op {
virtual int operator()(int a, int b) { return a + b; }
};
struct sub : bin_op {
virtual int operator()(int a, int b) { return a - b; }
};
// mul and div similarly.
std::map<char, bin_op *> ops;
add a;
sub s;
mul m;
div d;
ops['+'] = &a;
ops['-'] = &s;
ops['*'] = &m;
ops['/'] = &d;
Then to carry out an operation, you do something like this:
auto b = ops.find(operation);
if (b != ops.end())
std::cout << b->second(val1, val2);
else
std::cerr << "unknown operation: " << operation << "\n";
One obvious advantage of this is that it makes it fairly simple to add new operations: define a new class derived from bin_op to carry out your new operation, add an instance of that to ops (with the character you want to trigger that operation), and off you go.

Why is the unsuitable overloaded function is called?

Why does the following code always prints "type is double"? (I have seen this code in StackOverflow)
#include <iostream>
void show_type(...) {
std::cout << "type is not double\n";
}
void show_type(double value) {
std::cout << "type is double\n";
}
int main() {
int x = 10;
double y = 10.3;
show_type(x);
show_type(10);
show_type(10.3);
show_type(y);
return 0;
}
http://en.cppreference.com/w/cpp/language/overload_resolution says:
A standard conversion sequence is always better than a user-defined conversion sequence or an ellipsis conversion sequence.
void show_type(double value) {
std::cout << "type is double\n";
}
if u comment above line then output will be
type is not double
type is not double
type is not double
type is not double
it means that compile always prefer the void show_type(double value) over void show_type(...).
in your case if you want call the method void show_type(...) pass the two or more arguments when u calling this method show_type(firstParameter,secondParameter)
#include <iostream>
void show_type(...) {
std::cout << "type is not double\n";
}
void show_type(double value) {
std::cout << "type is double\n";
}
int main() {
int x = 10;
double y = 10.3;
show_type(x);
show_type(10);
show_type(10.3);
show_type(y);
show_type(4.0,5); //will called this method show-type(...)
return 0;
}
now the output of above line will be
type is double
type is double
type is double
type is double
type is not double //notice the output here
more info on var-args

passing primitive data type to a function in c++

I want to implement a function like this
double d = string_to("1223.23",double);
int i = string_to("1223",int);
bool d = string_to("1",bool);
How can I pass the bool, int, double data type to implement this in c++?
Types line int, double and bool can only be passed as template parameters.
You can use templates like this:
#include <string>
#include <sstream>
#include <iostream>
template<typename DataType>
DataType string_to(const std::string& s)
{
DataType d;
std::istringstream(s) >> d; // convert string to DataType
return d;
}
int main()
{
double d = string_to<double>("1223.23");
int i = string_to<int>("1223");
bool b = string_to<bool>("1");
std::cout << "d: " << d << '\n';
std::cout << "i: " << i << '\n';
std::cout << "b: " << b << '\n';
}
As an alternative you can pass your numeric types by reference and rely on function overloading to select the correct function:
void string_to(const std::string& s, double& d)
{
d = std::stod(s);
}
void string_to(const std::string& s, int& i)
{
i = std::stoi(s);
}
void string_to(const std::string& s, bool& b)
{
std::istringstream(s) >> std::boolalpha >> b;
}
int main()
{
double d;
int i;
bool b;
string_to("1223.23", d);
string_to("1223", i);
string_to("true", b);
std::cout << "d: " << d << '\n';
std::cout << "i: " << i << '\n';
std::cout << "b: " << b << '\n';
}
Also you could templatize the second method (an exercise for the reader).
If you really want to do this, you can pass the type by using the typeid operator.
E.g. double d = string_to("1223.23", typeid(double));
Using the library functions atoi, stod would make more sense.
If you're aiming to write more uniform code then you could write a Converter object and use method overloading to get automatic selection by type.
class Converter
{
public:
void fromString(double& value, const char* string);
void fromString(int& value, const char* string);
void fromString(long& value, const char* string);
};
Here's another way that uses tag dispatching. You can compile and run this example.
#include <iostream>
#include <string>
#include <cmath>
namespace detail {
// declare the concept of conversion from a string to something
template<class To>
To string_to(const std::string&);
// make some models of the concept
template<>
int string_to<int>(const std::string& s) {
return atoi(s.c_str());
}
template<>
double string_to<double>(const std::string& s) {
return atof(s.c_str());
}
template<>
std::string string_to<std::string>(const std::string& s) {
return s;
}
// ... add more models here
}
// define the general case of conversion from string with a model tag
// note the unused parameter allows provision of a model that is never used
// thus the model will in all likelihood be optimised away
template<class To>
To string_to(const std::string& from, const To& /* model_tag is unused */)
{
// dispatch to correct conversion function using the To type
// as a dispatch tag type
return detail::string_to<To>(from);
}
using namespace std;
int main()
{
// examples
int a = string_to("100", a);
double b = string_to("99.9", b);
const string s = string_to("Hello", s);
cout << s << " " << a << " " << b << endl;
return 0;
}
output:
Hello 100 99.9

C++ not modifiable lvalue

When I run this code, I get the an error saying C.getRadius() isn't modifiable lvalue:
#include <iostream>
#include <conio.h>
using namespace std;
class Circle {
double x, y, r;
public:
Circle (double a=1.0, double b=1.0, double c=1.0) { x=a; y=b; r=c; }
~Circle() {}
double Area();
double getRadius();
};
class Conus {
double height;
Circle C;
public:
Conus (double , double , double , double );
~Conus() {};
double Volume();
void setRadius(double );
};
Conus::Conus(double h, double a, double b, double c)
: C (a, b, c)
{
height=h;
}
double Circle::Area() { return r*r*3.14; }
double Conus::Volume() { return C.Area()*height; }
double Circle::getRadius() { return r; }
void Conus::setRadius(double t ) { C.getRadius()=t; }
int main() {
double a=2.4, b=3.5, r=5.4, h=5.9;
Circle Wre (a, b, r) ;
Conus Konusi (h, a, b, r) ;
cout << "Wris centris koordinatebia: " << a << " da " << b << ", radiusi: " << r
<< ". Wris fartobia :" << Wre.Area() << endl;
cout << "Konusis fudzis centris koordinatebia: " << a << " da " << b << ", radiusi: " << r
<<endl<< "konusis moculobaa: " << Konusi.Volume() << endl;
Konusi.setRadius(r+3);
cout << Konusi.Volume() << endl;
_getch();
return 0;
}
getRadius() returns a copy of the object's radius, not a reference to it, so you can't use it for modification. So the following expression:
C.getRadius()=t;
attempts to modify a temporary copy, which isn't allowed. (The reason that its not allowed is that otherwise that code would compile but do nothing useful, giving a subtle bug rather than an easily identified compile error).
There are various options:
return a reference, double & getRadius();
add a void setRadius(double); function, and use that for modification
make the radius public; there's little point in using accessors unless they're necessary to enforce invariants.
If you do want accessor functions, you should keep the existing double getRadius(), but declare it const. That will allow you to get, but not modify, the radius of a constant object.
This is a not a correct assignment, you are attempting to modify a temporary copy of the r not r itself:
C.getRadius()=t;
One way to fix this would be to add this method to Circle:
void setRadius( double t ){ r = t ; }
and call like:
void Conus::setRadius(double t ) { C.setRadius( t ); }
this is a great article Understanding lvalues and rvalues in C and C++ and the first example is similar to the problem you were facing just now.