Setting Default Parameters in C++ - c++

I have a little question about how default values are given to function parameters in C++. The problem I faced is probably due to my lack of understanding as to where the parameters are supposed to be declared/defined in the function prototype or the function header, or both? Codes are below with the errors noted:
#include <iostream>
using namespace std;
float volume(float l, float w, float h);
int main() {
float length;
float width;
float height;
cout << volume() << endl; // Here, with 'volume()' underlined, it says:
//no matching function for call to 'volume()'
cout << "Length: ";
cin >> length;
cout << "Width: ";
cin >> width;
cout << "Height: ";
cin >> height;
cout << "Volume = " << volume(length, width, height) << endl;
}
float volume(float l = 1, float w = 1, float h = 1){
float vol = l * w * h;
return vol;
}
In another attempt, here's what happened:
#include <iostream>
using namespace std;
float volume(float l = 1, float w = 1, float h = 1);
int main() {
float length;
float width;
float height;
cout << volume() << endl;
cout << "Length: ";
cin >> length;
cout << "Width: ";
cin >> width;
cout << "Height: ";
cin >> height;
cout << "Volume = " << volume(length, width, height) << endl;
}
float volume(float l = 1, float w = 1, float h = 1){ //Here, Xcode says that
// that the error is: Redefinition of default argument. < which I believe I understand.
float vol = l * w * h;
return vol;
}
In my last attempt, which is the one that worked, I did this:
#include <iostream>
using namespace std;
float volume(float l = 1, float w = 1, float h = 1);
int main() {
float length;
float width;
float height;
cout << volume() << endl;
cout << "Length: ";
cin >> length;
cout << "Width: ";
cin >> width;
cout << "Height: ";
cin >> height;
cout << "Volume = " << volume(length, width, height) << endl;
}
float volume(float l, float w, float h){
float vol = l * w * h;
return vol;
}
Could someone please explain to me the logic behind why the latter worked while the first two did not? Is there another way that the code would still work in the same way with the parameters specified elsewhere or the default values set in some place else? Are there any conventions or more favored practices in this area?
Adam

C++ and C are parsed top-down. When the compiler interprets a statement, it doesn't know about things it hasn't read yet.
In your first example, you declare a function called "volume", prototyped as taking 3 floats and returning a float. You then try to call a function called "volume" that takes no parameters, which doesn't exist yet (it would be a different function, since C++ supports polymorphism). You later define a function that can take 0, 1, 2, or 3 floats, but it is both too late and has an incompatible prototype to the first.
Your second example intuitively makes sense to be wrong, kind of like defining variables twice, but I don't have any specific information about why it is invalid code when the default values are identical.
Default parameters must be specified in the function prototype, which must occur prior to first usage in order for the compiler to know about it. Typically, you would put the prototypes with their default values in a header file that gets included above the code.
One thing to watch out for when dealing with default parameters from a shared header file, especially if you use it with dynamic libraries: The default values for the parameters are stored with the caller, and not the function being called. That is, if you update the function with new default values and don't rebuild the code calling that function, the old defaults will still be used by the calling code.

Adding to the above answer from Bjarne Stroustrup
A default argument is type checked at the time of the function declaration and evaluated at the time of the call. Default arguments may be provided for trailing arguments only. For example:
int f (int, int =0 , char * =0 ); // ok
int g (int =0 , int =0 , char *); // error
int h (int =0 , int , char * =0 ); // error
A default argument can be repeated in a subsequent declaration in the same scope but not changed.
For example:
void f (int x = 7 );
void f (int = 7 ); // ok
void f (int = 8 ); // error: different default arguments
void g () { void f (int x = 9 ); // ok: this declaration hides the outer one }
Declaring a name in a nested scope so that the name hides a declaration of the same name in an outer scope is error prone.

Default values could be defined in function declaration, as you done in your third attempt. This means usually they're appeared in header files, although this is not a rule.
Note that function declarations are scoped. This means that you could have more than one declaration for a function as long as they have different scopes:
void f(int);
int main() {
f(3); // argument should specified.
void f(int = 1);
f(); // calls f(1)
}
void f(int n = 2) {
}
void g() {
f(); // calls f(2)
}
In your second attempt you put default values on both declaration and definition of the function. This cause the compiler to confused because they are in the same scope.

Related

invalid type 'float*[float]' for array subscript

I want to display the range of x and f(x) and keep f(x) in array but i always get this error:
invalid type 'float*[float]' for array subscript
can someone help me? I'm still stuck.
Here's the code:
#include <iostream>
#include <cmath>
#include <math.h>
using std::cin;
using std::cout;
using namespace std;
void displayValue(float funx[], float j, float x);
int main()
{
float num9[]={};
float a, r;
displayValue(num9, a, r);
return 0;
}
void displayValue(float funx[], float j, float x)
{
float i;
cout << "Please enter range of x: " << endl;
for (i=0; i<1; i++)
{
cin >> x >> j;
}
for (float i=1; i<=160.5; i++)
{
x+=0.5;
funx[i]=1/sin(x)+1/tan(x);
//1.2 Display f(x) and x within the range
}cout << x << " = " << funx[i] << "\n";
}
The problems you're trying to solve aren't actually problems you need to solve. There's a lot going wrong in this code that can simply be removed because you're using the wrong tools.
You don't need an array here. If you did you'd need to allocate one, not pass in something that's empty, or you'd be using it out of bounds. In C++ for arrays like this use std::vector.
That being said, here's a simplified version of the code:
#include <iostream>
#include <cmath>
#include <math.h>
// Don't add "using namespace std", that separation exists for a reason.
// Separate the math function to make it clear what's being done
float f(const float x) {
return 1/sin(x)+1/tan(x);
}
// Define your functions before they're used to avoid having to declare
// then later define them.
void displayValue(const float min, const float max, const float step = 0.5)
{
for (float x = min; x <= max; x += step)
{
// Note how the f(x) function here is a lot easier to follow
std::cout << "f(" << x << ") = " << f(x) << std::endl;
}
}
int main()
{
std::cout << "Please enter range of x: " << std::endl;
// Capture the range values once and once only
float min, max;
std::cin >> min >> max;
// Display over the range of values
displayValue(min, max);
return 0;
}
There's some important C++ fundamentals here:
float num9[]={}; is not an empty array that you can later add to, it is a permanently zero-length array, or in other words, it's useless.
Pay close attention to the variables you've defined and avoid defining them twice in the same scope.
Turn on all your compiler warnings while you're learning to be alerted to potential problems. C++ is full of nuances and gotchas.

What is wrong with this C++ class? [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 4 years ago.
Improve this question
Here is the code that I have so far:
#include <iostream>
using namespace std;
class Rectangle
{
private:
double width, height;
public:
Rectangle();
double Set(double x, double y);
double getArea();
double getPerimeter();
};
Rectangle::Rectangle()
{
width = 1;
height = 1;
}
double Rectangle::Set(double x, double y)
{
width = x;
height = y;
}
double Rectangle::getArea()
{
double area = height * width;
return area;
}
double Rectangle::getPerimeter()
{
double perimeter = (width * 2) + (height * 2);
return perimeter;
}
int main()
{
double width, height;
cout << "Enter the width and height of a rectangle:";
cin >> width >> height;
cout << "The area is " << Rectangle::getArea << " and the perimeter is " << Rectangle::getPerimeter << endl;
}
When running this code I get the error : "'Rectangle::getArea': non-standard syntax; use '&' to create a pointer to member"
I get the same error about the Rectangle::getPerimeter
I am not sure what the problem is, I am new to making classes in C++ obviously, so I am having some trouble. Any suggestions?
There are several problems with your code.
1.) You never instantiate the class (i.e. create an object of that class type.) Having two variables with the names width and height is not the same as having an object of the type Rectangle.
2.) You are trying to call a non-static member function as if they were static member functions. Member functions are called via objects, for example
rect.getArea() where rect is an object of the type Rectangle.
3.) You are missing the parentheses at the function call. Whenever you get the message non-standard syntax, use & to create a pointer to a member it usually means that you have forgotten the parentheses at a function call.
What you want is probably something like:
int main()
{
double width, height;
cout << "Enter the width and height of a rectangle:";
cin >> width >> height;
Rectangle rect;
rect.Set(width, height);
cout << "The area is " << rect.getArea() << " and the perimeter is " << rect.getPerimeter() << endl;
}
1st create the object of Rectangle() class and then call the respective methods.
Rectangle rect;/* object of rectangle class */
your main() looks like
int main() {
double width, height;
cout << "Enter the width and height of a rectangle:";
cin >> width >> height;
Rectangle rect;/* object of rectangle class */
/* calling set method and passing the parameter */
rect.Set(width,height);
cout << "The area is " << rect.getArea() << " and the perimeter is " << rect.getPerimeter() << endl;
return 0;
}
As If i understood correctly you don't need Set() method actually, instead of this you do the same stuff using constructor by passing parameters.
parameterized constructor instead of Set() method
Rectangle::Rectangle(double x, double y) {
width = x;
height = y;
}
And create objects like
Rectangle rect(width,height);/* it will be called automatically */
For starters this member function returns nothing
double Rectangle::Set(double x, double y)
{
width = x;
height = y;
}
So it should be defined like
void Rectangle::Set(double x, double y)
{
width = x;
height = y;
}
It seems you mean
//...
cin >> width >> height;
Rectangle r;
r.Set( width, height );
cout << "The area is " << r.getArea() << " and the perimeter is " << r.getPerimeter() << endl;
The functions getArea and getPerimeter should be declared as constant member functions
double getArea() const;
double getPerimeter() const;
because they do not change objects of the type Rectangle.
It would be logical consistent if the class had a constructor with two parameters
Rectangle( double width, double height );
And the method Set should be split into two methods like setWidth and setHeight.

Uninitialized Local Variable

I'm new and just learning C++ and came across this problem that I've spent maybe an hour trying to fix and researching answers on but I cant seem to figure out what I'm doing wrong. I'm using Visual Studios as my IDE, the most recent version.
#include "stdafx.h"
#include <iostream>
#include "constant.h"
//height of the tower
double towerHeight(double x)
{
using namespace std;
cout << "Enter a height for the tower" << '\n';
cin >> x;
return x;
}
//the number of seconds since the ball has been dropped to determine the distance
double secondsSinceDrop(double x)
{
using namespace std;
cout << "How long has it been since you dropped the ball (Seconds): ";
cin >> x;
return x;
}
//finds how far off the ground the ball is
double currentBallHeight(double x, double y)
{
return y * constant::gravity - x;
}
//prints how far off the ground the ball is
void printResult(double x, double y)
{
using namespace std;
if (currentBallHeight(x, y) < 0)
cout << "At " << y << " the ball is on the ground." << '\n';
else
cout << "At " << y << " the ball is at: " << currentBallHeight(x, y) << '\n';
}
int main()
{
double x = towerHeight(x);
double y = secondsSinceDrop(x);
printResult(x,y);
return 0;
}
This is the Error Code
- chapter 2 comprehensive quiz (part 2).cpp(46): error C4700: uninitialized local variable 'x' used
-Line (46) is - double x = towerHeight(x);
I've been getting this and I've changed my code around to get it down to just this one error but i cant figure out how to fix it. Its probably something simple and I'm dumb for overlooking it but any help would be greatly appreciated.
These lines will be throwing errors
because the variable 'x' you are sending as an argument does not exist in the scope of main
int main()
{
-> double x = towerHeight(x);
-> double y = secondsSinceDrop(x);
printResult(x,y);
return 0;
}
Instead you could try something like this.
#include "stdafx.h"
#include <iostream>
#include "constant.h"
using namespace std;
//height of the tower
double towerHeight()
{
double height;
cout << "Enter a height for the tower" << '\n';
cin >> height
return height;
}
//the number of seconds since the ball has been dropped to determine the distance
double secondsSinceDrop()
{
double seconds;
cout << "How long has it been since you dropped the ball (Seconds): ";
cin >> seconds;
return seconds;
}
//finds how far off the ground the ball is
double currentBallHeight(double x, double y)
{
return y * constant::gravity - x;
}
//prints how far off the ground the ball is
void printResult(double x, double y)
{
if (currentBallHeight(x, y) < 0)
cout << "At " << y << " the ball is on the ground." << '\n';
else
cout << "At " << y << " the ball is at: " << currentBallHeight(x, y) << '\n';
}
int main()
{
double height = towerHeight();
double seconds = secondsSinceDrop();
printResult(height, seconds);
return 0;
}
Some tips that I would recommend
Declare your variables as much as relevant to you instead of using 'x/y/z'
There is no need to add the using namespace std; inside each function
Your first line of code in main() is double x = towerHeight(x);, what value of x are you sending to the function, when you have not initialized it.
When you are using a variable without initializing the value of it is undefined.
You can pass the variable as a reference to your function and accept the values inside it.
//height of the tower
void towerHeight(double &x)
{
using namespace std;
cout << "Enter a height for the tower" << '\n';
cin >> x;
}
//the number of seconds since the ball has been dropped to determine the distance
void secondsSinceDrop(double &y)
{
using namespace std;
cout << "How long has it been since you dropped the ball (Seconds): ";
cin >> y;
}
int main()
{
double x = 0.0, y = 0.0;
towerHeight(x);
secondsSinceDrop(y);
printResult(x, y);
return 0;
}
You seem to be struggling to connect the mental dots on what the computer is doing when you
declare variables with an initial value
define function parameters
return a value from a function
Not sure how this question will fair with the SO community as the preference is for Q/A that is succinct and reusable (maybe some editing can help) but for your benefit let me explain some of these concepts.
Let's start with a variable declaration
int x = 5;
int y = x;
When you define int x; it creates a space in RAM for an integer (4 bytes). Adding the = 5 initializes it immediately. It's important that the value on the right side of = (5 in this case) is known before the computer tries to make space for x.
It's fine to use values that aren't constant for variables like this (notice the second line in the example) but x has to be known before you declare y. In other words, this would obviously be a problem:
int y = x;
int x = 5;
For this same reason, the line: double x = towerHeight(x); is problematic because you're using x when you call towerHeight before ever defining x
When you define a function's parameters:
double towerHeight(double x) {
This tells the computer that you are going to copy the value from whatever called towerHeight to a new place in RAM and call it "x". This means that the value outside of the function doesn't get modified. Consider the following example:
double towerHeight(double x) {
x = 5;
std::cout << x << std::endl; // outputs 5
}
int main() {
double x = 10;
towerHeight(x);
std::cout << x << std::endl; // outputs 10
return 0;
}
Even though x was changed in towerHeight that was a "different copy of x" which also happened to be called the same name.
When you return a value from a function, in the same manner as passing a function argument, the return value is copied and used in places of the function call. Let's modify the previous example slightly:
double towerHeight(double x) {
x = 5;
return x;
}
int main() {
double x = 10;
x = towerHeight(x); // returns the value "5"
std::cout << x << std::endl; // Outputs "5"
return 0;
}
You can think of towerHeight(x) being replaced by "5" so the code would read x = 5;
Conclusion
You should try and use different variable names for
function arguments (the variables/values you pass to the function)
function parameters (what they are called inside the function)
to avoid this kind of confusion. Though there may be times where using the same name makes sense (i.e. passing by reference, which is another question). It's important for you to be aware of what's really going on.
Here is what you probably intend to do:
double towerHeight()
{
double height;
std::cout << "Enter a height for the tower" << std::endl;
std::cin >> height;
return height;
}
double secondsSinceDrop()
{
double seconds;
std::cout << "How long has it been since you dropped the ball (Seconds): ";
std::cin >> seconds;
return seconds;
}
double currentBallHeight(double y0, double t)
{
return y0 - (constant::gravity * t * t / 2);
}
void printResult(double y0, double t)
{
double currentHeight = currentBallHeight(y0, t);
if (currentHeight < 0)
std::cout << "At " << t << "s the ball is on the ground." << std::endl;
else
std::cout << "At " << t << "s the ball is at: " << currentHeight << std::endl;
}
int main()
{
double y0 = towerHeight();
double t = secondsSinceDrop();
printResult(y0, t);
return 0;
}
Summarizing what I've changed:
Renamed x to y0 since y(0)/h(0) is typically used for "initial height" in physics classes, and similarly y with t (though time would be an even better name).
Don't pass anything to towerHeight or secondsSinceDrop; you're not trying to give those functions something, you're trying to get something out of them.
Move the definition of x from a function parameter to a local variable defined in the function for towerHeight and secondsSinceDrop
Removed the duplicated call to currentBallHeight (no need to do the same math twice, it takes time to crunch numbers after all, however small in this case)
Rewrote for proper usage of std::cout and std::endl
Rewrote the currentBallHeight equation to match constant free-fall kinematics (y(t) = y(0) - 0.5g * t^2) as an added bonus (assuming constant::gravity > 0)
At some point it will be valuable for you to become aware of the more technical terminology and definitions for the concepts I've outlined here. Here are some recommended readings (just to get you started; keep learning, always):
Sequence Points
Parameters and Arguments
Passing by Reference vs by Value
Passing pointers vs by Reference
Making sure you understand what using namespace std; does and why you should never use it
Rewrite your function as following:
//height of the tower
double towerHeight()
{
double x;
using namespace std;
cout << "Enter a height for the tower" << '\n';
cin >> x;
return x;
}
and in int main(){} rewrite following line:
double x = towerHeight();
I guess this will do but you can actually modify your double secondsSinceDrop(double x); function this way as it doesn't really need a double value as parameter.

Types of constructors in classes

I am writing a class for college and I have a problem with constructors..
I have to create a class to calculate P and V of a cylinder. I need functions set(), to set the values, get H, get R to get values and P and V to calculate the P and V. I also need 3 constructors, first one to ask the user to enter the values for R and H, second one to set them to 10 and 5.5 and third one to initialize them to 3 and 1.
#include <iostream>
using namespace std;
class Cilindar{
public:
Cilindar();
Cilindar(float R, float H);
float getH();
float getR();
void set();
float Plostina(float R, float H);
float Volumen(float R, float H);
private:
float radius;
float visina;
};
void Cilindar::set(){
cout << "Vnesi go radiusot" << endl;
cin >> radius;
cout << "Vnesi ja visinata" << endl;
cin >> visina;
}
float Cilindar::getH(){
return visina;
}
float Cilindar::getR(){
return radius;
}
float Cilindar::Plostina(float R, float H){
return 2 * R * 3.14 * (R + H);
}
float Cilindar::Volumen(float R, float H){
return R * R * 3.14 * H;
}
Cilindar::Cilindar(){
set();
cout << "Plostinata iznesuva: " << Plostina(radius, visina) << endl;
cout << "Volumenot iznesuva: " << Volumen(radius, visina) << endl;
}
Cilindar::Cilindar(float R, float H){
cout << "Plostinata iznesuva: " << Plostina(R, H) << endl;
cout << "Volumenot iznesuva: " << Volumen(R, H) << endl;
}
int main()
{
Cilindar c1, c2(10, 5.5), c3;
return 0;
}
This is what I have so far, I made the first constructor to ask the user, second one with 10 and 5.5 but third one I don't know how can I initialize the values to the constructor, because a constructor with 2 arguments already exists, so what is another way to do it?
Thank you.
Just call the constructor with 2 arguments again (with different parameters).
Cilindar c1, c2(10, 5.5), c3(3, 1);
There is no need for another constructor.
Good luck.

trouble with error code

/* This program */
using namespace std;
#include <iostream>
#include <cmath>
#include <iomanip>
#include <fstream>
void readit();
void calcit(int, int);
void writeit(float, float, float);
int distvels[4] = {15, 25, 35, 45};
int main()
{
readit();
system("pause");
return 0;
}
void readit()
{
int targetdist, angl;
cout << "Enter the distance (meters) to the target:" << endl;
cin >> targetdist;
cout << "Enter the angle to fire the cannon:" << endl;
cin >> angl;
cout << "\n---------------\n\n";
calcit (targetdist, angl);
}
void calcit(int targetdist, int angl)
{
double distvals[4];
double tyme[4];
double maxhite[4];
for (int i=0; i<4; i++) {
distvals[i] = (2 * sin(angl) * cos(angl) * (distvels[i] * distvels[i]))/9.8;
tyme[i] = (2 * cos(angl) * distvels[i])/9.8;
maxhite[i] = ((cos(angl) * cos(angl)) * (distvels[i] * distvels[i]))/9.8;
}
writeit(distvals, tyme, maxhite);
}
void writeit(float distvals[4], float tyme[4], float maxhite[4])
{
cout << "Velocity " << "time " << "height " << "distance " <<endl;
for (int i=0; i<4; i++) {
cout << distvals[i] << " " << tyme[i] << " " << maxhite[i] << " " << endl;
}
whenever I run the program I keep getting this error code cannot convert double* to float for argument 1 to void writeit(float, float, float). I've tried everything I can think of to get rid of it with no luck. Can anyone help?
You declared the function as:
void writeit(float, float, float);
but the definition has it as:
void writeit(float distvals[4], float tyme[4], float maxhite[4])
{
// ...
}
Fix the declaration to match:
void writeit(float[4], float[4], float[4]);
It's also worth pointing out at this juncture that this doesn't do what you think it does. In fact, it's the same as this:
void writeit(float[], float[], float[]);
which is the same as this:
void writeit(float*, float*, float*);
That's because you can't pass an array by value, so it degrades into a pointer-to-the-start-of-the-array instead.
However, you can pass it by reference and keep the dimensions:
void writeit(float (&)[4], float (&)[4], float (&)[4]); // declaration
void writeit(float (&distvals)[4], float (&tyme)[4], float (&maxhite)[4]) // definition
{
// ...
}
I'd even recommend passing it as reference-to-const, as you won't be changing it:
void writeit(float (&)[4], float (&)[4], float (&)[4]);
void writeit(const float (&distvals)[4], const float (&tyme)[4], const float (&maxhite)[4])
{
// ...
}
It would also be easier if you used a std::vector<float>, but that's another discussion.
Plenty to think about there; hope it helps.
Edit Just noticed another problem, in that you're trying to pass an array of double to a function that will be expecting an array of float! Pick one and stick with it.
The error is exactly as you note -- writeit is expecting a pointer to an array of floats and you're trying to pass it an array of doubles, which are a different size. The easiest fix would be to declare the args of writeit to be arrays of doubles, so they match. Barring that, you need to copy to arrays of floats before passing (converting each element as you copy)
The function prototype is different from the function definition. So, change it to -
void writeit(double*, double*, double*);
And the function definition to -
void writeit(double distvals[], double tyme[], double maxhite[])
{
// ......
}
Notice that the array size (i.e., optional, in fact compiler won't consider it) because array decays to a pointer. It is the reason why usually array size is also sent as an argument to the functions and is a good practice.