Defining Array Default Parameters of a Class Constructor C++ [closed]

I’m trying to make a class to create a normal shape (equilateral shape) using OpenGL on Mac.

The given parameters are a center coordinate (double center[2]), a radius from center to a vertex (double radius), and a number of sides (int sides):

#include "../vendors/GLFW/glfw3.h"
#include <cmath>

class EquilateralShape {
    public:
        int sides;
        double center[2];
        double radius;
        
        double default_center[2] = {0.0, 0.0};

        EquilateralShape(int sidesIn = 3, double centerIn[2] = default_center, double radiusIn = 1.0) {
            sides = sidesIn;
            center[0] = centerIn[0];
            center[1] = centerIn[1];
            radius = radiusIn;
        }

        // rendering the shape
        void render() {
            // calculating vertices of the polygon
            double previous_vertex[2] = {center[0] + radius, center[1]};
            for(int i = 1; i < sides + 1; i++) {
                // determining if angle  is greater than 90, 180, 270, or 360
                double angle = (360*i)/sides;
                bool x_neg = false;
                bool y_neg = false;
                if (angle > 270) {
                    angle = 360 - angle;
                    y_neg = true;
                } else if (angle > 180) {
                    angle = -1 * (180-angle);
                    y_neg = true;
                    x_neg = true;
                } else if (angle > 90) {
                    angle = 180 - angle;
                    x_neg = true;
                }

                // calculating vertices
                double y_coord = radius * sin(angle);
                double x_coord = radius - radius * cos(angle);

                // updating coordinates to match unit circle group
                if (x_neg == true) {
                    x_coord *= -1;
                }
                if (y_neg == true) {
                    y_coord *= -1;
                }

                // rendering triangle
                glBegin(GL_TRIANGLES);
                glVertex2d(x_coord, y_coord);
                glVertex2d(previous_vertex[0], previous_vertex[1]);
                glVertex2d(center[0], center[1]);
                glEnd();

                // updating previous vertex
                previous_vertex[0] = x_coord;
                previous_vertex[1] = y_coord;
            }
        }
};

…but when I compile, I’m told:

error: invalid use of non-static data member 'default_center'

This refers to the defaults parameter I passed for center.

Originally I tried not including a default parameter, but that also gave me an error:

error: missing default argument on parameter 'centerIn'

I also tried passing the default parameter as an array, in the form double centerIn[2] = {0.0, 0.0} but the compiler told me it interpreted the comma between the array entries as a new argument.

3

Parameter default values are substituted in by the compiler only at the call site. They are not part of the parameter itself. So, you can’t use a non-static class member as a parameter’s default value.

For example, this code:

void someFunction {
    EquilateralShape shape;
    ...
}

is actually treated by the compiler as this code:

void someFunction {
    EquilateralShape shape(3, ??.default_center, 1.0); // ERROR
    ...
}

See the problem? Whose default_center member do we use? The shape object doesn’t exist yet, so we can’t use its default_center member.

If you make the class member be static and const then it will work the way you want, eg:

class EquilateralShape {
    public:
        static const double default_center[2];

        EquilateralShape(int sidesIn = 3, const double centerIn[2] = default_center, double radiusIn = 1.0) {
            ...
        }
};

// and then in some .cpp file:
const double EquilateralShape::default_center[2] = {0.0, 0.0};

Or, in C++17 and later, you can inline the initialization of the static member:

class EquilateralShape {
    public:
        inline static const double default_center[2] = {0.0, 0.0};
        // or:
        static constexpr double default_center[2] = {0.0, 0.0};

        EquilateralShape(int sidesIn = 3, const double centerIn[2] = default_center, double radiusIn = 1.0) {
            ...
        }
};

And then this code:

void someFunction {
    EquilateralShape shape;
    ...
}

is actually this code:

void someFunction {
    EquilateralShape shape(3, EquilateralShape::default_center, 1.0); // OK
    ...
}

This is a follow up answer to Remy’s, showing the shortcomings of using (in particular) C-style arrays when you should be using proper types instead.

Your code can be reduced to the following minimal example, substituting Point for your array of 2 doubles:

struct Point { double x; double y; };

class Shape
{
public:
    Shape (Point centre = { }) { /* ... */ }
};

int main ()
{
    Shape my_shape;
}

See how simple and expressive that is? By using the type system properly your problem has magically disappeared, with a lot more benefits besides which you will discover along the way.

It’s always better to use std::array than raw arrays. There are far less ways to get confused:

#include <array>
#include <cstdint>

struct EquilateralShape {
     std::uint32_t sides;
     std::array<double, 2> center;
     double radius;
     /*rest of declarations*/
};

then use constructor member initialzer list:

EquilateralShape(int sides_in = 3, std::array<double, 2> center_in = {}, double radius_in = 1.0):
    sides{sides_in},
    center{center_in},
    radius{radius_in}
{/*Extra init*/};

If you intend to keep all data members publicly accessible, then it’s better to provide default values for members and rely on aggregate construction with designated initializations:

struct EquilateralShape {
     std::uint32_t sides = 3;
     std::array<double, 2> center = {};
     double radius = 1.0;
     /*No constructors*/
};

EquilateralShape shape1 {.radius{3.0}};

Raw arrays have very different semantics from ordinary types in C++. In some old C texts they are referred to as reference types; but since reference has a clear and very distinct definition in C++, those old C terms are no more used.

Raw array instances have following properties:

  1. They can’t be passed to functions by value. Instead they decay to pointers to first element, when passed to functions.
  2. They can’t be copy/move constructed
  3. They can’t be assigned to or from, as a whole object. Each element needs to be individually assigned.

The above properties makes using raw pointers difficult. But all of theses restrictions can be circumvented if the raw array is wrapped within an aggregate class, and that is exactly what std::array does. On the unlikely event where compiler falls short of properly optimize std::array, the data and size member functions provide the interface to switch back to C style code; but I seriously recommend against doing that.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật