How to initialize static members of a class? [duplicate]
Asked Answered
D

1

-1

I have written this code. It is giving no compile time errors but a runtime error. Can you please tell me what is wrong with this code?

It is giving this runtime error -> strap info: vpid 1: terminated with signal 11

    #include <iostream>

    class Color
    {
    public:
        static Color White, Black, Red, Green, Blue;

        unsigned char red, green, blue;

        static void static_Color();

        Color(unsigned char _red
        , unsigned char _green
        , unsigned char _blue)
        : red(_red), green(_green), blue(_blue)
        {
            static_Color();
        }
        
        Color()
        {
            static_Color();
        }
    };
    
    Color Color::White, Color::Black
    , Color::Red, Color::Green, Color::Blue;
    
    void Color::static_Color()
    {
        static bool called_before = false;

        if(called_before)
            return;

        Color::White = Color(255, 255, 255);
        Color::Black = Color(0, 0, 0);
        Color::Red = Color(255, 0, 0);
        Color::Green = Color(0, 255, 0);
        Color::Blue = Color(0, 0, 255);

        called_before = true;
    }
    
    int main()
    {
        std::cout << (int) Color::Red.red;
    }

A needed feature static constructor.

Disapproval answered 15/10, 2023 at 19:11 Comment(11)
Did you try (inside Color) to code: static Color white={255,255,255}; and did you compile with g++ -Wall -Wextra -g then use the GDB debugger ?Unprofitable
Perfect use for a debugger. You'll see that static_color is called recursively until stack overflow.Frippery
Right here Color Color::White is a call to the Color constructor, which calls static_Color(), which then calls the Color constructor 5 more times. Each of them then calls static_Color() again. Only ends when running out of memory for the calls.Controller
Can't you make a constexpr here that can be used instead?Reiner
@Reiner I made the members constexpr and inline. Now, it is saying Color is incomplete. Also a constexpr cannot be changed later. I have come up with this example. What if I don't want to make it constexpr??Disapproval
Maybe functionality is broken in g++.Disapproval
"Maybe functionality is broken in g++" So there is either a bug in the compiler, or a bug in your code, Want to make a bet? :-) But seriously, the error sounds like you tried to put Color values inside the Color class. You cannot do that because the class is not fully known to the compiler until after the }; at the end.Controller
@Controller I removed static_Color(); call from constructors and added it to the main method. Now, it is working fine. The constructor and the static constructor were calling each other. Although there is a bool called_before but Compiler still got confused.Disapproval
@PraveenO'Connell If you need to call a function in main to initialize your library, it seems like a bit of a failure. Can't you define the constant Color values outside the Color class like I showed? You then have a header only library that doesn't require a call to any function.Gravelblind
@Ted Lyngmo but then there will be multiple definitions of const values if the library has multiple header files.Disapproval
@PraveenO'Connell No. Aninlined variable will be linked ot the same variable. You can print the addresses of the pre-defined Colors in different translation units and you'll see that they are the same in all of them.Gravelblind
G
2

You don't need a static_Color() function. Just initialize them with the proper values where the static colors are defined:

class Color {
public:
    static Color White, Black, Red, Green, Blue;

    unsigned char red = 0, green = 0, blue = 0;

    Color(unsigned char _red, unsigned char _green, unsigned char _blue)
        : red(_red), green(_green), blue(_blue) {}

    Color() = default;
};

// Here:
Color Color::White = Color(255, 255, 255);
Color Color::Black = Color(0, 0, 0);
Color Color::Red = Color(255, 0, 0);
Color Color::Green = Color(0, 255, 0);
Color Color::Blue = Color(0, 0, 255);

Right now, your the call to static_Color() in your constructor causes infinite recursion since every construction of a Color will cause a call to static_Color() that will again construct more Colors.


An alternative to having static member variables is to make some constants in your namespace. I've called the namespace Color too. You figure out a better one:

namespace Color {
class Color {
public:
    unsigned char red = 0, green = 0, blue = 0;

    constexpr Color(unsigned char _red, unsigned char _green, unsigned char _blue)
        : red(_red), green(_green), blue(_blue) {}

    Color() = default;
};

inline constexpr Color White = Color(255, 255, 255);
inline constexpr Color Black = Color(0, 0, 0);
inline constexpr Color Red = Color(255, 0, 0);
inline constexpr Color Green = Color(0, 255, 0);
inline constexpr Color Blue = Color(0, 0, 255);
}  // namespace Color
Gravelblind answered 15/10, 2023 at 20:2 Comment(2)
What if I want to initialize these objects in header file? Maybe because it has header only and no cpp file.Disapproval
@PraveenO'Connell That's not what you have in your question though. I'm not sure that is possible since you can't make them inline since Color isn't complete yet. I added an alternative.Gravelblind

© 2022 - 2025 — McMap. All rights reserved.