I'm new to Cpp and I'm just trying to construct a very basic 'Circle' class. Below is my code
#include <iostream>
#include <cmath>
#include <typeinfo>
class Circle {
private:
const double pi = 3.14159265358979323846;
double radius;
double area;
double perimeter;
public:
void set_rad(double rad){
radius = rad;
area = pi*pow(rad,2);
perimeter = 2*pi*rad;
}
double get_attr() {
double circle_attr[3] = {radius, area, perimeter};
std::cout << typeid(circle_attr).name() << std::endl;
return *circle_attr;
}
};
int main(){
Circle aCircle;
aCircle.set_rad(5);
aCircle.get_attr();
return 0;
}
The code runs and behaves as expected. However, if, in the return line to the method get_attr
, I replace *circle_attr
with circle_attr
, then I get the error cannot convert 'double*' to 'double' in return
. However, circle_attr
is already an array of doubles. That's what I intialised it as and it's what Cpp is telling me, since when I call typeid(circle_attr).name()
I get back A3_d
, which I assume is short for Array3_double. So what is going on here?
CodePudding user response:
The actual issue you're having is the attempt to return a C-array from a function. That's not a thing that can be done. If you want, the smallest possible change would be to change your function to look like this:
#include <array>
// [...]
std::array<double, 3> get_attr() {
std::array<double, 3> circle_attr{radius, area, perimeter};
std::cout << typeid(circle_attr).name() << std::endl;
return circle_attr;
}
You stated that your function was supposed to return A double, and then you tried returning an array of doubles, or really just the radius in your case.
std::array
is a bit of a mess, though, since the size is part of the type information.
Here's your code, with some tweaks to get it more in line with C and also completely rewriting your get_attr()
function.
#include <cmath>
#include <iostream>
#include <tuple> // CHANGED: Needed for structured binding usage in get_attr()
class Circle {
private:
const double pi = 3.14159265358979323846;
double radius = 0.0; // CHANGED: Kept the default member initialization going
double area = 0.0;
double perimeter = 0.0;
public:
Circle() = default; // CHANGED: Added constructors
Circle(double r)
: radius(r), area(pi * std::pow(radius, 2)), perimeter(2 * pi * radius) {}
void set_rad(double rad) {
radius = rad;
area = pi * pow(rad, 2);
perimeter = 2 * pi * rad;
}
// CHANGED: Using C 17 feature called structured bindings; also made function
// const, since it shouldn't alter the data
auto get_attr() const { return std::make_tuple(radius, area, perimeter); }
};
int main() {
Circle aCircle(5.0); // CHANGED: Now we can use constructors
// aCircle.get_attr(); // NOTE: Didn't even try to save info anywhere
auto [radius, area, perimeter] = aCircle.get_attr();
std::cout << "Radius: " << radius << "\nArea: " << area
<< "\nPerimieter: " << perimeter << '\n';
return 0;
}
Output:
Radius: 5
Area: 78.5398
Perimieter: 31.4159
We added constructors, which are a fundamental part of C OOP. You can see in main()
how constructors allow us to initialize at the declaration site.
I also left one your original lines in main()
to note that even if get_attr()
worked, you didn't save the info at all. So you wouldn't have had it anyway.
Your get_attr()
function has been written to take advantage of a C 17 feature called structured bindings. It also takes advantage of another feature called CTAD, just to keep the one line in get_attr()
succinct.
In order for you to test this, you'll need to add the -std=c 17
flag to the compile command you're using. It's good practice to always specify the standard version you're using.