I have a class Color that holds values for the red, green, blue, and alpha channels of a color. The class constructor lets you create a new color by specifying values for the four channels. However, for convenience, I would also like to have some "premade" colors available for the programmer. For example instead of having something like
DrawBox(new Color(255, 0, 0));
you would be able to say
DrawRectangle(Color::Red);
Where Color.Red is an instance of Color that lives inside the Color class. How can I declare these instances of Color inside the Color class? I'm sure there's a name for this technique, but I had no idea what search terms to use when I was looking for help online.
I'm not using any built-in or publicly-available classes or libraries because this is part of a personal exercise in creating a basic graphics stack.
Thanks for your help!
First of all, avoid using new. You could use Color as simple value-type.
Now as an answer to your question, yes, you can do that as:
//color.h
typedef unsigned char byte;
class Color
{
public:
//declaration
const static Color Red;
const static Color Green;
const static Color Blue;
public:
Color(byte red, byte green, byte blue);
};
//define the static members in color.cpp file
#include "color.h"
const Color Color::Red(255,0,0);
const Color Color::Green(0,255,0);
const Color Color::Blue(0,0,255);
Then use Color::Red as you want to use.
Related
I am trying to add serial support for an existing class in SFML library. I am trying to save colors to be loaded later. From the documents, it says that Cereal is easily extensible to other types, but I have no clue how to do so. Barring creating a SerialColor class and reimplementing sf::Color inside it, and adding a serialize member in there, is there a way to do this? I would really like to not rewrite the 5 classes I need from SFML to be serializeable.
I am part way through converting Color to SerialColor, and so far have achieved the following:
SerialColor.hpp
#pragma once
#include <SFML/Graphics.hpp>
#include <SFML/Config.hpp>
class SerialColor: sf::Color
{
public:
static const SerialColor Black; ///< Black predefined color
static const SerialColor White; ///< White predefined color
static const SerialColor Red; ///< Red predefined color
static const SerialColor Green; ///< Green predefined color
static const SerialColor Blue; ///< Blue predefined color
static const SerialColor Yellow; ///< Yellow predefined color
static const SerialColor Magenta; ///< Magenta predefined color
static const SerialColor Cyan; ///< Cyan predefined color
static const SerialColor Transparent; ///< Transparent (black) predefined color
SerialColor(sf::Uint8 red, sf::Uint8 green, sf::Uint8 blue, sf::Uint8 alpha = 255);
private:
SerialColor(sf::Color c);
sf::Color color;
template<class Archive>
void serialize(Archive& archive, std::uint32_t const version) {
archive(CEREAL_NVP(this->color.r),
CEREAL_NVP(this->color.g),
CEREAL_NVP(this->color.b)
);
}
};
SerialColor.cpp
#include "SerialColor.h"
SerialColor::SerialColor(sf::Uint8 red, sf::Uint8 green, sf::Uint8 blue, sf::Uint8 alpha = 255) {
this->color = sf::Color(red, green, blue, alpha);
}
SerialColor::SerialColor(sf::Color c) {
this->color = sf::Color(c);
}
This is currently not completely implemented, so it does not work. However this feels like overkill to add 1 function to a class. If extending is the correct way, could you provide what is considered the normal way to add this capability? This just feels wrong.
Instead of trying to extend the class directly, you can provide cereal with a function that tells it how to serialise your custom data types, e.g:
namespace cereal {
template<class Archive>
void serialize(Archive& archive, sf::Color c) {
archive(CEREAL_NVP(c.r),
CEREAL_NVP(c.g),
CEREAL_NVP(c.b)
);
}
You can choose to add something like the code above to your own header file (something like 'Serialize.hpp') and include that instead of cereal.hpp, or you can extend your cereal headers directly (i.e. something like cereal/types/sf_color.hpp).
It's really up to you where you put this code but as long as it is visible, cereal will automatically be able to serialise the sf::Color type.
The following class is given:
class Button {
public:
enum Color{RED, GREEN, BLUE};
Color color = RED;
void setToBlue() {
Color* colorPtr = &color;
*colorPtr = BLUE;
//colorPtr->BLUE;
}
}
If I call setToBlue(), will BLUE not be destroyed until Button is destroyed? Why is the out commented instruction not valid?
Your code is perfectly valid.
*colorPtr = BLUE;
copies the value of BLUE into the pointed to object. Which in this case is color, which is a member of Button and thus is guaranteed to exist until the Button object is destroyed.
Note that
void setToBlue() {
color = BLUE;
}
Is exactly the same in this case.
To answer your edit:
Why is the out commented instruction not valid?
Because what operator -> does is the same as (*colorPtr).. The . operator is the member access operator, an enum doesn't have any members to access and thus it makes no sense.
I think there's a fundamental confusion here about what an enum is. Probably the best way to see them for this sample is as a #define.
Imagine that instead you had
#define BLUE 2
and then did colour = BLUE; this would breakdown to colour = 2
Since '2' is now hard coded in the memory of the binary, it's scope is global.
Consider the following Enum Class in Java:
package com.gousslegend.deepov;
public enum Color
{
WHITE, BLACK;
private Color opposite;
static
{
WHITE.opposite = BLACK;
BLACK.opposite = WHITE;
}
public Color getOppositeColor()
{
return opposite;
}
}
How can I achieve the same thing with C++11?
Is is possible to have enum methods with C++11?
Should I put my enum in a separate class/file with C++?
Thanks
How can I achieve the same thing with C++11?
In C++ you would be better off defining an enum, along with a free-standing function:
enum Color {BLACK, WHITE};
Color getOppositeColor(Color c) {
static Color opposite[] = {WHITE, BLACK};
return opposite[c];
}
If you are set on modeling Java exactly, make a class with two static members BLACK and WHITE, and use it instead of enum. The use would be limited, though: for instance, you wouldn't be able to use your enum values in switch cases.
Is is possible to have enum methods with C++11?
No
Should I put my enum in a separate class/file with C++?
You should put enum definition and a function prototype in a header; implementation of the function goes in a separate C++ file.
C++'s enums are simple enumerated values, they're not full-fledged classes (enum classes in C++ only provide some additional type-safety).
I would take the following approach to implement the equivalent to how Java's enums are used here:
// Header file
class Color {
Color *opposite_p;
public:
Color(Color *opposite_pArg) : opposite_p(opposite_pArg) {}
Color &opposite() { return *opposite_p; }
static Color WHITE, BLACK;
};
// .C file
Color Color::WHITE(&BLACK);
Color Color::BLACK(&WHITE);
Then, Color::WHITE.opposite() returns Color::BLACK, and COLOR::BLACK.oppsoite() returns Color::WHITE.
I have class like following:
class Car
{
public:
Car();
// Some functions and members and <b>enums</b>
enum Color
{
Red,
Blue,
Black
};
Color getColor();
void setColor(Color);
private:
Color myColor;
}
I want to:
access to Color values as Color::Red. It is really hardly to understand code when Car::Red is used, when class have a lot enums, subclasses etc.
use type Color as function argument or return value
use variable type Color in switch
I know 3 partial solutions:
Using embedded class Color and enum in it
Using embedded namespace Color and enum in it
Using enum class
1 and 2 solutions solves a Color::Red accession problem, but I can't use functions like Color getColor() and void setColor(Color).
3 solution has a problem: VS2010 doen't support enum class. GCC v.4.1.2 doesn't support it too. I don't know about later versions of gcc.
Yes, I'm working on cross-platform project.
I have found this solution, but it seems ... heavy.
I hope somebody can help me here :)
In current C++ (i.e. C++11 and beyond), you can already access enum values like that:
enum Color { Red };
Color c = Color::Red;
Color d = Red;
You can go further and enforce the use of this notation:
enum class Color { Red };
Color c = Color::Red;
// Color d = Red; <-- error now
And on a sidenote, you now define the underlying type, which was previously only possible with hacky code (FORCEDWORD or so anyone?):
enum class Color : char { Red };
Name the enum inside the nested class (as example one):
class Car
{
public:
struct Color
{
enum Type
{
Red,
Blue,
Black
};
};
Color::Type getColor();
void setColor(Color::Type);
};
When I want to do something like this I tend to use a namespace and a typedef outside of th namespace (though usually I'm doing this globally rather than inside a class). Something like this:
namespace colors
{
enum Color
{
Red,
Blue
...
}
}
typedef colors::Color Color;
This way you use the namespace to get at the actual colors, but the Color type itself is still globally accessible:
Color myFav = colors::Red;
Hey all, I'm working on cleaning up my code from previous semesters.
Previously I created a 151 color swatch library in c++. However because of my time crunch and lack of experience, I created it entirely as a block of define statements. Which, for hard coding values into spots worked fine. However there are some obvious weaknesses to this approach.
What I have panned out so far, is to create a namespace 'swatch' and inside the namespace I would have an enumeration for the valid colors. I would also have a 'getSwatch' function, or something similar, that would return a vec3 (a class of mine, represents a vector of 3 elemets, with some nice functionality), and the function would use a switch statement to go through the valid swatches.
It would look something like this:
namespace swatch{
enum color{
red,
blue,
green
}
inline
const vec3 getColor(const color& c){
// Switch and return red blue or green.
}
}
My Question: I'd like to know how you might suggest doing this? Benifits of preformance, and usability is what I'm most interested in.
Thanks in advance friends,
Happy coding.
Edit: I just changed the example to make more sense to people who don't know how I use my vec class. (i.e: Everybody but me). Also, you can just look at the other anwsers for usage. They made a good guess on passing rgb values to the constructor, thats not how I did it, but I can still follow along just fine with what you mean.
Use a lookup table:
/************* .h *************/
enum color{
red,
blue,
green,
colors_count
}
const vec3 &getColor(color c)
{
extern const vec3 colors_table[colors_count];
return colors_table[c];
}
/************* .cpp *************/
extern const vec3 colors_table[colors_count] = {
vec3(255, 0, 0), // red
vec3(0, 0, 255), // blue
vec3(0, 255, 0), // green
};
You didn't write anything about purpose of using templates so I just eliminated them. If you explain more then I will help maybe.
// EDIT
It's very simple and very fast.
In c++, enum values are not just some identifiers, they are numbers. If you don't specify other they will be fallowing numbers starting from 0: 'red' is 0, 'blue' is 1, 'green' is 2 and 'colors_count' is 3 (see http://www.google.com/search?q=c%2B%2B+enum).
You can use these numbers to index an array. Then you simply pick an item from an array at given index.
You could just use a std::map<color, vec>:
class ColorClass {
private:
std::map<color, vec> colors;
// ... etc ...
And then you have a big init function that sets it up:
colors["red"] = new vec(0xFF, 0x00, 0x00);
colors["blue"] = new vec(0x00, 0xFF, 0x00);
// ... etc ...
And then your getColor function is just:
return colors[color];
Done!