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.
Related
Im practicing memberwise assignment in C++, where you can set the values of one object to another object of the same class. The idea of the program is to initialize a rectangle object with some values and create another rectangle object but assign the value of the first into the second.
Its giving me an error, which is posted below, and I can't figure out what it is and its driving me nuts lol
This is my Rectangle.h
#ifndef RECTANGLE_H
#define RECTANGLE_H
class Rectangle {
private:
double length;
double width;
public:
Rectangle(double, double);
double getLength() const;
double getWidth() const;
};
Rectangle::Rectangle(double l, double w) {
length = l;
width = w;
}
double Rectangle::getWidth() const { return width; }
double Rectangle::getLength() const { return length; }
#endif
This is my Rectangle.cpp
#include <iostream>
#include "rectangle.h"
using namespace std;
int main()
{
Rectangle box1(10.0, 10.0);
Rectangle box2;
cout << "box1's width and length: " << box1.getWidth() << ", " << box1.getLength() << endl;
cout << "box2's width and length: " << box2.getWidth() << ", " << box2.getLength() << endl;
box2 = box1;
cout << "box1's width and length: " << box1.getWidth() << ", " << box1.getLength() << endl;
cout << "box2's width and length: " << box2.getWidth() << ", " << box2.getLength() << endl;
return 0;
}
This is the error when I compile.
skipper~/Desktop/Programming/Memberwise: g++ rectangle.cpp
rectangle.cpp:7:12: error: no matching constructor for initialization of
'Rectangle'
Rectangle box1(10.0, 10.0);
^ ~~~~~~~~~~
./rectangle.h:4:7: note: candidate constructor (the implicit copy constructor)
not viable: requires 1 argument, but 2 were provided
class Rectangle {
^
./rectangle.h:4:7: note: candidate constructor
(the implicit default constructor) not viable: requires 0 arguments, but 2
were provided
1 error generated.
EDIT: This is how I was able to make it work. I moved everything into rectangle.cpp and gave the constructor default arguments.
EDITED rectangle.cpp
#include <iostream>
using namespace std;
class Rectangle {
private:
double length;
double width;
public:
//Rectangle();
Rectangle(double = 0.0, double = 0.0);
double getLength() const;
double getWidth() const;
};
int main()
{
Rectangle box1(10.0, 10.0);
Rectangle box2;
cout << "box1's width and length: " << box1.getWidth() << ", " << box1.getLength() << endl;
cout << "box2's width and length: " << box2.getWidth() << ", " << box2.getLength() << endl;
box2 = box1;
cout << "box1's width and length: " << box1.getWidth() << ", " << box1.getLength() << endl;
cout << "box2's width and length: " << box2.getWidth() << ", " << box2.getLength() << endl;
return 0;
}
Rectangle::Rectangle(double l, double w) {
length = l;
width = w;
}
double Rectangle::getWidth() const { return width; }
double Rectangle::getLength() const { return length; }
The only changes I made were giving default arguments to my user-defined constructor. However, it wasn't able to work when the changes were in rectangle.h. However, when I moved the class and member function definitions to rectangle.cpp it was able to work. So, I got the program to work but I didn't address the real issue, which is when the class and member function definitions are in rectangle.h, it won't compile.
If anyone has faced this problem and has found a solution to this, please let me know how you did it. Thanks :)
In the line
Rectangle box2; // no default constructor, error
you are trying to invoke the default constructor of Rectangle. The compiler does not generate such a default constructor anymore, because your Rectangle has a user defined constructor that takes 2 parameters. Therefore, you need to specify the parameters, like
Rectangle box2(0,10);
The error I get when compiling your code is:
Rectangle.cpp:8:15: error: no matching function for call to 'Rectangle::Rectangle()'
Rectangle box2;
A solution is to create a default constructor for Rectangle, since it is not automatically generated anymore due to your user defined one:
Rectangle(); // in Rectangle.h
Rectangle::Rectangle(){} // in Rectangle.cpp (or Rectangle::Rectangle() = default; in C++11)
Another solution (and the preferable one, since it doesn't leave the data un-initialized) is to assign default arguments to your existing constructor.
Rectangle::Rectangle(double l = 0, double w = 0); // only in Rectangle.h
In this way, you make your class Default-Constructible.
A compiler generated default constructor is only generated if you have no defined constructors. You define a constructor, so if you want a default constructor you have to provide it yourself. Probably the easiest (arguably) is to provide it by using default arguments in your two argument constructor:
Rectangle(double l=0, double w=0)
Also you should use the inline keyword as shown below or you may find you get linker errors:
inline Rectangle::Rectangle(double l, double w) {
length = l;
width = w;
}
inline double Rectangle::getWidth() const { return width; }
inline double Rectangle::getLength() const { return length; }
I am trying to call a function in another class. I need to use the surface area function or the information that was stored in it from the previous class for another class. How would I go about that?
I have already tried HalfOpenCylinder::surfaceArea() and HalfOpenCylinder.surfaceArea() and neither worked.
//surface area function that I want to use for other class
double HalfOpenCylinder::surfaceArea(double height, double pi) {
double surfaceArea = (2 * pi * radius * height) + (pi * pow(radius, 2));
return surfaceArea;
}
To call a function from another class you need to first create an object (instance) of that class.
Using that object you can call a particular function
eg:
#include <iostream>
using namespace std;
class Student
{ // defining class
public:
int id;
void add(){
int x=1;
int y=2;
int z=x+y;
cout<<z<<endl;
}
};
int main() {
Student s1; // creating object of class
s1.id=20;
s1.add() // calling function of that class
return 0;
}
I have written a script that shows you how you can
"call a function in another class"
and
"use the surface area function or the information that was stored in it from the previous class for another class".
This is a script with many examples in it. It uses an updated version of your surfaceArea() method (method being the term since the function is defined from within a class). I have also included what output the script produces at the very bottom of the script.
You can copy and past this entire code segment into a C++ compiler and it should work for you. I compiled and tested it in Visual Studio 2015 Community. I went to new project, and created a "Win32 Console Application" in the C++ category.
// ConsoleApplication10.cpp : Defines the entry point for the console application.
//
// This class example was created to answer kittykoder's question on StackOverflow.
// Both of these need to be included
#include "stdafx.h"
#include <iostream>
// We need the std namespace
using namespace std;
// Here I am defining a struct so that you can easily take all the values out of the
// HalfOpenCylinder class at once, and even make a new Cylinder object with the values by
// using the struct in one of the two HalfOpenCylinder class constructors.
struct CylinderValues
{
public:
CylinderValues(double radius, double height, double surfaceArea) {
this->radius = radius;
this->height = height;
this->surfaceArea = surfaceArea;
}
__readonly double radius;
__readonly double height;
__readonly double surfaceArea;
};
// This is the class I saw in your example. Since it is named
// HalfOpenCylinder, I decided to treat it like an
// instantiatable object class, both because it makes sense name wise,
// and based on the context you provided in your question.
class HalfOpenCylinder
{
public:
// Pi is always 3.14, so there is no reason to make it a passable parameter
// like in your example. Thus I have made it a constant. It's a static constant because
// of the static function I've placed in this class to help in answering your question.
static const float pi;
// I have encapsulated the variables that make up this
// class's objects behind methods so that the surface area can be
// updated every time the radius or height values are changed.
double GetRadius() { return radius; }
void SetRadius(double value) { radius = value; UpdateSurfaceArea(); }
double GetHeight() { return height; }
void SetHeight(double value) { height = value; UpdateSurfaceArea(); }
double GetSurfaceArea() { return surfaceArea; }
// You can make a HalfOpenCylinder object with this constructor
HalfOpenCylinder(double radius, double height) {
this->radius = radius;
this->height = height;
UpdateSurfaceArea();
}
// You can use another HalfOpenCylinder object to make a new HalfOpenCylinder object using
// this constructor.
HalfOpenCylinder(CylinderValues values) {
radius = values.radius;
height = values.height;
surfaceArea = values.surfaceArea;
}
// This will return the struct needed to use the constructor just above this comment.
CylinderValues CopyValues() {
return CylinderValues(radius, height, surfaceArea);
}
// Here is your surface area calculation from your question
static double CalculateSurfaceArea(double radius, double height) {
return (2 * pi * radius * height) + (pi * pow(radius, 2));
}
private:
// Here are the values you wanted to be able to access from another class.
// You can access them using the methods above for getting and setting. The
// surfaceArea value is automatically recalculated if you change either the
// radius or height variable's values.
double radius;
double height;
double surfaceArea;
// This method is here so that HalfOpenCylinder objects can use the
// Surface area calculation. I could have copied and pasted the calculation
// code here to avoid calling the static method, but then I would be writing code
// more than need be. This way, you can update one and the other will be correct.
void UpdateSurfaceArea() {
surfaceArea = CalculateSurfaceArea(radius, height);
}
};
// This is honestly just here because the compiler yelled at me for defining a static
// constant inside a non-static class. Could'a gotten away with it in C#. Thank you compiler.
const float HalfOpenCylinder::pi = 3.141592;
// This is called a function since it is outside of any class (although,
// that is one of the few differences between functions and methods.
// Methods being, functions defined inside classes)
void ThisIsAFunction() {
cout << "This is the text from the function named: ThisIsAFunction";
}
// This class is just here to show you how to call functions and methods from inside classes
class CallFunctionAndMethodTester
{
public:
void MethodInsideTheClass() {
cout << "The below is printed from a function called in a class: \n";
// Here, I am calling a function from inside a class
ThisIsAFunction();
cout << "\n\nThe below is printed from a static method called in a class: \n";
// Here, I am calling a static method from inside a class
cout << HalfOpenCylinder::CalculateSurfaceArea(14.5, 50.5);
// Here, I am making an object instance from inside a class
HalfOpenCylinder bobTheCylinder(1.5, 5.4);
cout << "\n\nThe below is printed from an object's method called in a class: \n";
// Here, I am calling an object's method from inside a class
cout << bobTheCylinder.GetRadius();
}
};
// Ok. We made it. THIS main function is where we will use and
// test the classes we have made above.
int main() {
// Make a new cylinder object. No pointer, so it will be destroyed when the computer
// reads past main (which is the end of this program anyways).
cout << "Cylinder 1 Values: \n";
HalfOpenCylinder cylinder1(5.0, 10.0);
cout << cylinder1.GetRadius();
cout << "\n"; // <--just makin' a newline here
cout << cylinder1.GetHeight();
cout << "\n";
cout << cylinder1.GetSurfaceArea();
cout << "\n\n"; // <--just makin' two newlines here
// Change the object's height. The surface area updates automatically.
cout << "Cylinder 1 new surface area once Height is changed: \n";
cylinder1.SetHeight(20.5);
cout << cylinder1.GetSurfaceArea();
cout << "\n\n";
// Make a second Cylinder using the first cylinder's values.
cout << "Cylinder 2 Values: \n";
HalfOpenCylinder cylinder2(cylinder1.CopyValues());
cout << cylinder2.GetRadius();
cout << "\n";
cout << cylinder2.GetHeight();
cout << "\n";
cout << cylinder2.GetSurfaceArea();
cout << "\n\n";
// Here I'm using the static CalculateSurfaceArea function to use the surface area
// method without having to make a new HalfOpenCylinder object.
cout << HalfOpenCylinder::CalculateSurfaceArea(5.0, 10.0);
cout << "\n\n";
// Here I am making an object of type CallFunctionAndMethodTester so that I can call
// the method inside it that is using my example of how to call functions and methods
// from within classes.
CallFunctionAndMethodTester tester;
cout << "Everything printed to the console after this line is printed using functions and methods that are called from inside classes. \n\n";
tester.MethodInsideTheClass();
int meh;
cin >> meh;
return 0;
}
/* Here is the output of this code when the program runs:
Cylinder 1 Values:
5
10
392.699
Cylinder 1 new surface area once Height is changed:
722.566
Cylinder 2 Values:
5
20.5
722.566
392.699
Everything printed to the console after this line is printed using functions and methods that are called from inside classes.
The below is printed from a function called in a class:
This is the text from the function named: ThisIsAFunction
The below is printed from a static method called in a class:
5261.38
The below is printed from an object's method called in a class:
1.5
*/
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.
Im practicing memberwise assignment in C++, where you can set the values of one object to another object of the same class. The idea of the program is to initialize a rectangle object with some values and create another rectangle object but assign the value of the first into the second.
Its giving me an error, which is posted below, and I can't figure out what it is and its driving me nuts lol
This is my Rectangle.h
#ifndef RECTANGLE_H
#define RECTANGLE_H
class Rectangle {
private:
double length;
double width;
public:
Rectangle(double, double);
double getLength() const;
double getWidth() const;
};
Rectangle::Rectangle(double l, double w) {
length = l;
width = w;
}
double Rectangle::getWidth() const { return width; }
double Rectangle::getLength() const { return length; }
#endif
This is my Rectangle.cpp
#include <iostream>
#include "rectangle.h"
using namespace std;
int main()
{
Rectangle box1(10.0, 10.0);
Rectangle box2;
cout << "box1's width and length: " << box1.getWidth() << ", " << box1.getLength() << endl;
cout << "box2's width and length: " << box2.getWidth() << ", " << box2.getLength() << endl;
box2 = box1;
cout << "box1's width and length: " << box1.getWidth() << ", " << box1.getLength() << endl;
cout << "box2's width and length: " << box2.getWidth() << ", " << box2.getLength() << endl;
return 0;
}
This is the error when I compile.
skipper~/Desktop/Programming/Memberwise: g++ rectangle.cpp
rectangle.cpp:7:12: error: no matching constructor for initialization of
'Rectangle'
Rectangle box1(10.0, 10.0);
^ ~~~~~~~~~~
./rectangle.h:4:7: note: candidate constructor (the implicit copy constructor)
not viable: requires 1 argument, but 2 were provided
class Rectangle {
^
./rectangle.h:4:7: note: candidate constructor
(the implicit default constructor) not viable: requires 0 arguments, but 2
were provided
1 error generated.
EDIT: This is how I was able to make it work. I moved everything into rectangle.cpp and gave the constructor default arguments.
EDITED rectangle.cpp
#include <iostream>
using namespace std;
class Rectangle {
private:
double length;
double width;
public:
//Rectangle();
Rectangle(double = 0.0, double = 0.0);
double getLength() const;
double getWidth() const;
};
int main()
{
Rectangle box1(10.0, 10.0);
Rectangle box2;
cout << "box1's width and length: " << box1.getWidth() << ", " << box1.getLength() << endl;
cout << "box2's width and length: " << box2.getWidth() << ", " << box2.getLength() << endl;
box2 = box1;
cout << "box1's width and length: " << box1.getWidth() << ", " << box1.getLength() << endl;
cout << "box2's width and length: " << box2.getWidth() << ", " << box2.getLength() << endl;
return 0;
}
Rectangle::Rectangle(double l, double w) {
length = l;
width = w;
}
double Rectangle::getWidth() const { return width; }
double Rectangle::getLength() const { return length; }
The only changes I made were giving default arguments to my user-defined constructor. However, it wasn't able to work when the changes were in rectangle.h. However, when I moved the class and member function definitions to rectangle.cpp it was able to work. So, I got the program to work but I didn't address the real issue, which is when the class and member function definitions are in rectangle.h, it won't compile.
If anyone has faced this problem and has found a solution to this, please let me know how you did it. Thanks :)
In the line
Rectangle box2; // no default constructor, error
you are trying to invoke the default constructor of Rectangle. The compiler does not generate such a default constructor anymore, because your Rectangle has a user defined constructor that takes 2 parameters. Therefore, you need to specify the parameters, like
Rectangle box2(0,10);
The error I get when compiling your code is:
Rectangle.cpp:8:15: error: no matching function for call to 'Rectangle::Rectangle()'
Rectangle box2;
A solution is to create a default constructor for Rectangle, since it is not automatically generated anymore due to your user defined one:
Rectangle(); // in Rectangle.h
Rectangle::Rectangle(){} // in Rectangle.cpp (or Rectangle::Rectangle() = default; in C++11)
Another solution (and the preferable one, since it doesn't leave the data un-initialized) is to assign default arguments to your existing constructor.
Rectangle::Rectangle(double l = 0, double w = 0); // only in Rectangle.h
In this way, you make your class Default-Constructible.
A compiler generated default constructor is only generated if you have no defined constructors. You define a constructor, so if you want a default constructor you have to provide it yourself. Probably the easiest (arguably) is to provide it by using default arguments in your two argument constructor:
Rectangle(double l=0, double w=0)
Also you should use the inline keyword as shown below or you may find you get linker errors:
inline Rectangle::Rectangle(double l, double w) {
length = l;
width = w;
}
inline double Rectangle::getWidth() const { return width; }
inline double Rectangle::getLength() const { return length; }
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.