Getting member variables values set and then passed to a function c++ - c++

Probably a dumb question, I want to be able to use the passed in A & B values through the default constructor and use them in my functions like get(), but every time i do it gives the value of 0, how do i set the values of A & B and then be able to use them in my other functions. I know i could just pass the value into the get function from the main but i dont want to do it that way.
I have this in the .h,
class example
{
private:
int A, B;
public:
example();
example(int, int);
int get(int, int);
};
then in the .cpp
example::example()
{
cout << hello;
}
example::example(int x, int y)
{
A = x;
B = y;
}
int example::get(int c, int d)
{
int k = c + d / A;
return k;
}
And in the main()
int c = 10;
int d = 12;
int x = 2;
int y = 1;
example obj1(x, y);
example obj2;
int k = obj2.get(c, d);
cout << k;
Im thinking i should see an answer of 10 + 12 / 2 however its 10 + 12 / 0, not sure where i am going wrong if anyone could help thanks!

example(x, y);
does not do anything. It creates a temporary object that goes immediately out of scope. Then
example obj1;
should not compile, as you don't have a default constructor. If it compiles it means that you have provided a default constructor, which is invoked (and which probably doesn't do any initialization). However in your case you want to invoke the constructor example::example(int, int). The correct way of doing it is to define
example obj1(x, y);

Related

Undefined behaviour of Designated initializers in C++

The following C++20 program is accepted without any warning in all compiles I have tried:
struct A { const int & x = z; int y = x; int z; };
int main()
{
return A{.z=3}.y;
}
https://gcc.godbolt.org/z/nqb95zb7c
But every program returns some arbitrary value. Is it right to assume that this is undefined behavior?
Members are initialized in the order they appear in the class definition, hence the designated initializer is not that relevant, and also this
struct A {
const int & x = z;
int y = x; // <- read of indeterminate value !
int z = 42; // <- doesn't really matter because y is initialized before !
};
int main() {
return A{}.y;
}
is undefined for the same reason.
See also the example from cppreference:
struct A {
string str;
int n = 42;
int m = -1;
};
A{.m=21} // Initializes str with {}, which calls the default constructor
// then initializes n with = 42
// then initializes m with = 21
The example is actually to illustrate something else, but it also shows how members are initialized in order.

How to access a class constructor parameter from the another class parameter

STRUGGLING WITH C++ CONSTRUCTOR ARGUMENTS
So, I've just came from TS/JS/Py and trying to understand C++ concepts. But I'm struggling with using the parameter of constructor of the class FOR declaring default value for an argument. Here is the code I'm trying to run:
double Phythagorean_Hypotenuse (int& a, int& b ) {
return sqrt((a * a) + (b * b));
};
class Triangle {
public:
int a;
int b;
double c;
Triangle(int a_param, int b_param, double c_param = Phythagorean_Hypotenuse(a_param, b_param)) {
a = a_param;
b = b_param;
c = c_param;
}
};
and inside of the main function
Triangle mytri_1(10, 20);
std::cout << mytri_1.a << std:endl;
But when I try to run this code, IDE is throwing me some errors like
[Error] 'a_param' was not declared in this scope
or
[Error] call to 'Triangle::Triangle(int, int, double)' uses the default argument for parameter 3, which is not yet defined
So, please, can someone who can fix this answer the question?
Thanks.
There are some issues that prevent your code from compiling, namely:
Constructors do not have return type.
double c_param = Phythagorean_Hypotenuse(a_param, b_param) is not valid for a parameter, a_param, b_param will not be recognized.
Recommend change:
Since the result of a hypothenuse calculation will most likely be a decimal value, c should be a double.
You can do something like this:
Running sample
#include <iostream>
#include <cmath>
double Phythagorean_Hypotenuse (int& a, int& b ) {
return sqrt((a * a) + (b * b));
};
class Triangle {
public:
int a;
int b;
double c; //should be double
//initializer list is a good practice for member initialization
Triangle(int a_param, int b_param)
: a(a_param), b(b_param), c(Phythagorean_Hypotenuse(a, b)) {}
};
int main(){
Triangle mytri_1(10, 20);
std::cout << mytri_1.a << std::endl;
std::cout << mytri_1.b << std::endl;
std::cout << mytri_1.c << std::endl;
}
Output:
10
20
22.3607
As the compiler is pointing out, the other constructor arguments are not available as default parameters for the c_param argument. Rather than using default values, just overload the constructor, including one that just accepts 2 parameters. This constructor can then invoke the other constructor that accepts all 3:
// Constructor overload that accepts all 3 parameters
Triangle(int a_param, int b_param, double c_param):
a(a_param), b(b_param), c(c_param) {
}
// Constructor overload that accepts just a and b, call the other constructor
// to set all 3 members
Triangle(int a_param, int b_param):
Triangle(a_param, b_param, Phythagorean_Hypotenuse(a_param, b_param)) {
}
Default parameter values cannot reference other parameters. You can define two overloads, one of which delegates to the other, to do what you want:
class Triangle {
public:
double a;
double b;
double c;
Triangle(double a_param, double b_param, double c_param)
: a{a_param},
b{b_param},
c{c_param}
{}
Triangle(double a_param, double b_param)
: Triangle{a_param, b_param, Phythagorean_Hypotenuse(a_param, b_param)}
{}
};
Live Demo
A few other notes:
Class constructors do not have a return type. I changed void Triangle(...) to Triangle(...)
I used constructor initialization lists instead of assignment in the constructor's body. There's likely no difference for small primitive values like ints or doubles, but it's a good habit to get into and can make a big difference for more complex types
int doesn't make sense for the type of c (or a or b for that matter). The sides of a triangle are unlikely to all be integers
There's no reason to pass parameters to Pythagorean_Hypotenuse by reference. It's simpler and likely faster to pass them by value

Initialize parameter into constructor, other than the first one

I want to explicitly change the second parameter in a constructor of a struct, in the following scenario. Is it possible, if so, how?
struct foo{
int x;
int y;
foo(int a=4, int b=6){
x=a;
y=b;
}
};
int main(){
foo *f = new foo();
cout<<f->x<<" "<<f->y<<endl;
//4 6
foo *g = new foo(3,4);
cout<<g->x<<" "<<g->y<<endl;
//3 4
foo *h = new foo(3);
cout<<h->x<<" "<<h->y<<endl;
//3 6
//Can something like this be
//done in C++, if I want
//to change the value of the
//second variable only
foo *k = new foo(b = 13);
return 0;
}
Is it possible, if so, how?
It is not possible with constructor. In general, c++ does not support named keyword arguments to functions, and it is not possible to skip arguments even if they have a default, if you want to pass a non-default after it.
It will be possible without constructor using list initialisation syntax since C++20 using designated initialisers, if you use default member initialisers:
struct foo{
int x = 4;
int y = 6;
};
int main(){
foo f {.y = 4};
}
You can achieve something similar with tag dispatching; No need for future standard:
struct foo{
int x = 4;
int y = 6;
enum Xtag { Xinit };
enum Ytag { Yinit };
foo(int a, int b) : x(a), y(b) {}
foo(Xtag, int a) : x(a) {}
foo(Ytag, int b) : y(b) {}
};
int main(){
foo f(foo::Yinit, 4);
}
A solution using lambda that can be used without modifying an existing class. Following works with your definition of foo:
auto make_foo_x4 = [](int b) {
return foo(4, b);
};
foo f = make_foo_y(4);
The downside is that we have to explicitly repeat the default value of x, so this can break assumptions if the default is changed in class definition.

C++ overloaded function calling version of itself with more arguments

I am using function overload to have a general version of a behaviour and a more usual one. The usual function just picks a default value for the second argument that actually depends on the first, and the compiler is giving me an error because it does not even recognize the existence of the second function. I also tried to do it with default values, but because the default depends on the first argument, the compiler does not seem to accept it.
So, here are simplified examples just for illustration.
Function overloading case:
#include <stdio.h>
struct pair {
int x;
int y;
};
int func(pair a){
return func(a, a.y);
}
int func(pair a, int b) {
return a.x*b;
}
int main() {
pair z;
z.x = 2;
z.y = 4;
printf("%d\n", func(z));
printf("%d\n", func(z,12));
}
This gives me the error:
a.c: In function ‘int func(pair)’:
a.c:9:21: error: too many arguments to function ‘int func(pair)’
a.c:8:5: note: declared here"
Example with default values:
#include <stdio.h>
struct pair {
int x;
int y;
};
int func(pair a, int b = a.y) {
return a.x*b;
}
int main() {
pair z;
z.x = 2;
z.y = 4;
printf("%d\n", func(z));
printf("%d\n", func(z,12));
}
Gives me the following error: "local variable a may not appear in this context"
So, is there any way in C++ to emulate this behaviour? I never had this problem in other languages, like Java or even in ASP.
Thank you all.
In C and C++, before the function call, that function should be declared or defined. Here you are making a call to return func(a, a.y); but the function func(pair, int) has not yet been declared or defined.
You need to change the definitions of the two functions, or just declare the functions in the beginning of your code. As other answers have explained the first approach, here is the snippet with second approach.
#include <stdio.h>
//Function Declaration
int func(pair);
int func(pair, int);
struct pair {
int x;
int y;
};
int func(pair a){
return func(a, a.y);
}
int func(pair a, int b) {
return a.x*b;
}
int main() {
pair z;
z.x = 2;
z.y = 4;
printf("%d\n", func(z));
printf("%d\n", func(z,12));
}
Switch the order of the definitions of func(), such that the 2 argument version is defined before the one argument version. The compiler doesn't know the 2 argument version exists until it encounters the definition, so you can't call it until you've told the compiler it exists.
You have to change the order of the definitions:
int func(pair a, int b) {
return a.x*b;
}
int func(pair a){
return func(a, a.y);
}
LIVE DEMO
This is happening because in int func(pair a) you are calling int func(pair a, int b) which is not visible. Changing the order of definitions like above solves this problem.

How can the assignment from int to object be possible in C++?

class phone {
public:
phone(int x) { num = x; }
int number(void) { return num; }
void number(int x) { num = x; }
private:
int num;
};
int main(void)
{
phone p1(10);
p1 = 20; // here!
return 0;
}
Hi, guys
Just I declared a simple class like above one.
After that I assigned int value to the object that class, then it worked!
(I printed its value. It was stored properly)
If there is not a construct with int parameter, a compile error occurred.
So, I think it's related with a constructor. Is that right?
Please give me a good explanation.
Thanks.
This is legal because C++ interprets any constructor that can be called with a single argument of type T as a means of implicitly converting from Ts to the custom object type. In your case, the code
p1 = 20;
is interpreted as
p1.operator= (20);
Which is, in turn, interpreted as
p1.operator= (phone(20));
This behavior is really weird, and it's almost certainly not what you wanted. To disable it, you can mark the constructor explicit to disable the implicit conversion:
class phone {
public:
explicit phone(int x) { num = x; }
int number(void) { return num; }
void number(int x) { num = x; }
private:
int num;
};
Now, the constructor won't be considered when doing implicit conversions, and the above code will cause an error.