0

Coming from a Java background, I am used to the concept of making a class A, then creating class B to hold specific static instantiations of class A to use throughout the program. Some example Java code:

public class Color {
    public int r;
    public int g;
    public int b;

    public Color(int r, int g, int b) {
        this.r = r;
        this.g = g;
        this.b = b;
    }
}

public class Colors {
    public static final Color WHITE = new Color(255, 255, 255);
    public static final Color BLACK = new Color(0, 0, 0);
}

I have tried a class Color, with a struct Colors named colors, but I get linker errors as colors is reinstantiated in every file I include it in. What is the best way to do this in C++? Or am I trying to solve the problem in the wrong way?

Hong Ooi
  • 56,353
  • 13
  • 134
  • 187
  • `constexpr` might help. – Jarod42 Apr 11 '18 at 12:48
  • This isn't anywhere close to legal C++ - where is your actual attempt? – UnholySheep Apr 11 '18 at 12:48
  • by using const`const` – Petar Velev Apr 11 '18 at 12:48
  • 6
    Sounds like you could use a [good C++ book](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). That will teach you what the C++ syntax is, which is not the same as Java – NathanOliver Apr 11 '18 at 12:48
  • Sorry, could have been clearer, this is Java I wrote to try and illustrate what I would like to do in C++. – user3618747 Apr 11 '18 at 12:51
  • I'm happy to learn syntax from a textbook, but I'm more asking if this is something that is really done at all in C++. I imagine as a OOP language that there is something similar, but I would appreciate a point in the right direction. – user3618747 Apr 11 '18 at 12:52
  • 2
    "Or am I trying to solve the problem in the wrong way?" That's the one. They don't belong in a separate class but either the same one or the same namespace; even java doesn't usually create a separate class from what I remember it as static final color instances would be in the color class – UKMonkey Apr 11 '18 at 12:53
  • read about this regarding static members https://stackoverflow.com/questions/185844/how-to-initialize-private-static-members-in-c – Arkady Godlin Apr 11 '18 at 12:56
  • in c++ you dont use `new` everywhere all the time but rather very sparingly only when really needed – 463035818_is_not_an_ai Apr 11 '18 at 13:01
  • There is no equivalent as there can't be one. Making parallels between the two completely different languages is counter productive. – Ron Apr 11 '18 at 13:08
  • C++ is turing complete like Java or Assembly. So asking if something which can be done in Java can be done in C++ is pointless. Learning the language will teach you how you **can** solve a problem. Practicing the language will teach you how you **should** solve it (i.e. best practice). – too honest for this site Apr 11 '18 at 13:08

2 Answers2

0

Assuming that your problem is actually the color thing you presented, this would probably be the easiest way to achieve it:

struct Color
{
    int r, g, b;

    Color(int r, int g, int b)
    {
        this->r = r;
        this->g = g;
        this->b = b;
    }

    static Color WHITE() { return {255, 255, 255}; }
    static Color BLACK() { return {0, 0, 0}; }
};

https://godbolt.org/g/DBrM1C


If you for some reason need to be able to reference the static objects (i.e. there should be exactly one static object instance for every named color), you could declare them in the header (Colors.h) and initialize them in the associated compilation unit (Colors.cpp), but that is somewhat cumbersome and also means your compile time constants cannot be inlined/constant folded etc. by the compiler (without link-time optimization at least). It does protect you from recompilations of files that include Colors.h if the constants change though.


This method would be a (not much better) middle ground where there is still one static object instance per color but you can keep it to the header: https://godbolt.org/g/13krNc

Note however that, despite optimizations, the compiler cannot figure out that bar() should always return 255. Instead, it has to check in every call whether the static constants were initialized already and, if not, initialize them (which requires a lock for thread safety!).

Max Langhof
  • 23,383
  • 5
  • 39
  • 72
  • 1
    Your solution seems way too complicated, there is no problem with having constant objects instead of static functions: https://ideone.com/prJYrk – UnholySheep Apr 11 '18 at 13:20
  • @UnholySheep If you are ok with putting things in an extra namespace, that works too. – Max Langhof Apr 11 '18 at 13:23
  • using namespaces is a good practice, though my example would also work without it: https://ideone.com/J1twYz – UnholySheep Apr 11 '18 at 13:24
  • I meant "in the namespace instead of the/a class". Can you do the same as part of a class? If I had different color representations and a template like `template TColor bar() { return TColor::WHITE; }` in some shape or form, the namespace solution won't work. Example is trivial and beyond the scope of the question, I know, but I had exactly this kind of problem before. – Max Langhof Apr 11 '18 at 13:28
-2

In C++ an include is an actual include. That means, in contrast to Java imports, the code is actually copied.

When you now include your file multiple times, you have multiple occurrences of your code. That is why you need to protect your header code from being copied twice.

Solution 1: Write the following as the first line of your header file:

#pragma once

Solution 2 (more portable and widely recommended):

#ifndef MYHEADERFILENAME_H
#define MYHEADERFILENAME_H
// your header code goes here
#endif /* MYHEADERFILENAME_H */

Some more thoughts about your problem:

  1. Do not use a class for encapsulating constexpr values. This is not necessary in C++. In Java there cannot be something outside a class, but in C++ this is perfectly legal. Just declare your symbol and define it in your source file outside a class. You should declare it in your own namespace, though, to avoid name clashes.

  2. Maybe an enum class aka scoped enumeration comes closer to what you really want.

UniversE
  • 2,419
  • 17
  • 24
  • There is no question to begin with. I suspect that is why you are receiving the downvotes. – Ron Apr 11 '18 at 13:03
  • I am receiving downvotes, because I am one of the few, who read the question carefully enough. He said: "but I get linker errors as colors **is reinstantiated in every file I include it in**." And that is to what I responded. – UniversE Apr 11 '18 at 13:29
  • Could indeed be the case. – Ron Apr 11 '18 at 13:32