initialise const array inside class - c++

In Visual C++, how can I initialise a constant array inside of a class?
This is an example of how to do it outside of a class:
const char k_colors[] =
{
'R',
'G',
'B',
};
Now how do I need to change that? (I tried putting static in front of it, which didn't work)
Edit: You're right, I should just use single characters.

If you want it to be static, you'll need to initialize it outside the class:
class foo
{
public:
static const char k_colors[3];
foo() { }
};
const char foo::k_colors[] = {'a', 'b', 'c'};
Also, you probably want it to be a const char *[] since it looks like you're trying to initialize strings, so it'd be:
const char *foo::k_colors[] = {"Red", "Green", "Blue"};

I tried putting static in front of it, which didn't work
You can't initialise the static member array (or any member array) inside the class definition. Do it outside of the class definition:
class X
{
static const char* k_colors[3];
};
const char* X::k_colors[] = { "Red", "Green", "Blue" };

In C++11 you can use the constructor initializer list as mentioned
class A {
const int arr[2];
// constructor
A()
: arr ({1, 2})
{ }
};
Or you can use static const array
In header file:
class A {
static const int a[2];
// other bits follow
};
In source file (or in separate place from the declaration above)
const int A::a[] = { 1, 2 };
Of course you can always use std::vector<int> and for loop as well.

I think you can initialize through the constructor initializer list
Refer here
Also the char should be char*
Extract from the above link:
prior to C++11 you need to do just this to default-initialise each element of the array:
: k_colors()
With C++11 it is more recommended use uniform initialisation syntax:
: k_colors{ }
And that way you can actually put things into the array which you couldn't before:
: k_colors{"red","green"}

Related

C++ static array initialization with indexes

I have a static array in a class and an enum for the index of such array.
enum MyEnum
{
FIRST = 0,
SECOND,
LAST
}
class MyClass
{
public:
static string names[LAST];
}
I'd like to initialize my static array to associate a value of the array to each enum type like this:
names[FIRST] = "First";
names[SECOND] = "Second";
I know that I can initialize the array upon declaration like this static string names[] = {"First", "Second"}, but I want to explicitly assign the value to the corresponding enum to avoid errors.
In Java, there's a static block where you can do this kind of initialization, but I don't think that this is the case in C++. Is there an elegant way of doing this? I can't use std on my project, so the solution has to avoid any library usage.
Thanks in advance.
Write a function to initialize it. Function can't return an array - if you want to use an array, return a whole object that has an array inside it. Or you can return something dynamically allocated, a map or a vector.
#include <array>
#include <string>
enum MyEnum {
FIRST = 0,
SECOND,
LAST
};
std::array<std::string, LAST> construct_names() {
std::array<std::string, LAST> r;
r[FIRST] = "first";
r[SECOND] = "second";
return r;
}
static auto names = construct_names();
I can't use std on my project, so the solution has to avoid any library usage.
Roll your own types.
enum MyEnum {
FIRST = 0,
SECOND,
LAST
};
template<typename T, unsigned N>
struct MyArray {
T data[N];
T &operator[](unsigned i) {
return data[i];
}
};
MyArray<const char *, LAST> construct_names() {
MyArray<const char *, LAST> r;
r[FIRST] = "first";
r[SECOND] = "second";
return r;
}
static auto names = construct_names();
You may also want to read How to initialize private static members in C++? or similar, as for class initialization you need to do like, there will be some type repetition:
class MyClass {
public:
static MyArray<const char *, LAST> names;
};
MyArray<const char *, LAST> MyClass::names = construct_names();
Yes you can do it in simple way using __attribute__((init_priority(101))) and __attribute__((constructor(102)))
#include <string>
#include <iostream>
using namespace std;
enum MyEnum
{
FIRST = 0,
SECOND,
LAST
};
class MyClass
{
public:
static string names[LAST];
};
__attribute__((init_priority(101))) string MyClass::names[LAST];
__attribute__((constructor(102))) void foo()
{
MyClass::names[FIRST] = "First";
MyClass::names[SECOND] = "Second";
}
int main()
{
MyClass m;
for (int i = 0; i < LAST; i++) {
cout << m.names[i] << "\n";
}
}
Output:
First
Second
Explanation in simple:
Before even code loads, first it initialize string MyClass::names[LAST]; because we added __attribute__((init_priority(101))) then it calls foo() automatically, The function name can be any it does not matter, it can be init as well no need to be foo. The order of initialization is based on number 101 and 102. If we change the order then it wont work.
For more info refer: https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html#index-init_005fpriority-variable-attribute
Declaimer: This initialization is not bound to the class, if you keep on adding like this for all the classes then you are in big trouble and you need to keep on maintain a list of orders. This inits are for the entire binary or library

Convert C array literal to work in C++ constructor?

I have some C code that I'm trying to convert/wrap into a C++ class. I ran into some C literal arrays(correct me if I'm calling them wrong) and I'm not sure how to initialize them in the C++ constructor since I don't think you can do literals, which I think are compile time specific, to something that is runtime specific.
Should I just explicitly define the array to be of a certain size and just do a strcpy, or some such, of the literal to the array in the constructor?
char sysUpTime[] = {1,3,6,1,2,1,1,3,0};
As an alternative to initializer lists or string manipulation, you could use something like the following (if you really wanted to):
struct Wrapper
{
template <size_t N>
Wrapper(const char(&arr)[N]) : vec(arr, arr+N) { }
vector<char> vec;
};
I've left everything public due to chronic laziness on my part :). You can then initialise like this:
char foo[] = { 1, 2, 3, 4, 5 };
Wrapper bar(foo);
copy(bar.vec.begin(), bar.vec.end(), ostream_iterator<int>(cout, ", "));
Could just use std::string to store OID then initialize it in member initializer list for example:
#include <string>
class Wrapper
{
public:
Wrapper() : sysUpTime("1.3.6.1.2.1.1.3.0") { }
private:
std::string sysUpTime;
};
Or use C++11 std::array
class Wrapper
{
public:
Wrapper() : sysUpTime{{1,3,6,1,2,1,1,3,0}} { }
public:
std::array<char, 10> sysUpTime;
};
The main problem when passing different size c-style arrays to a constructor is that you must pass the size along with it. Here's an example of putting the array into a member vector:
#include <vector>
#include <iostream>
struct Test
{
std::vector<char> sysUpTime;
Test(const char sysUpTime[], size_t size) :
sysUpTime(sysUpTime, sysUpTime + size)
{ }
};
int main()
{
const char sysUpTime[] = {1,2,3,4,5};
Test test(sysUpTime, sizeof(sysUpTime) / sizeof(char));
}
Unfortunately I know of no way to do this without using a dynamic array (vector), aside from using templates which means that you'll get a separate class instantiated for each and every change in the size of your array.

How can I initialize a static const vector that is a class member in c++11?

I need to initialize a static const vector that is a class member.
I have tried:
static const vector<string> vr ({"2", "3", "4"});
static const vector<string> vr = {"2", "3", "4"};
static const vector<string> vr {"2", "3", "4"};
However, none of these work.
I am using Eclipse with mingw. (I have enabled c++11)
Static variable initialization is done outside of the class, like this:
class Example
{
static const vector<string> vr;
// ...
};
const vector<string> Example :: vr ({"hello", "world"});
Declare your static members in your class definition, but define them outside.
class MyClass {
public:
// declaration
static const std::vector<std::string> vec;
};
// definition
const std::vector<std::string> MyClass::vec = ...;
The exception to this is integral types,
class MyClass {
public:
// declaration and definition
static const int MAX_BURRITOS = 5;
};
You did limit your question to C++11 but I will drop this here for future visitors who find this in search results.
If you're able to move forward to C++17, you can use const static inline to initialize the static member within the class declaration and no longer need to have it outside the class.
Like this:
#include <iostream>
#include <string>
#include <vector>
class Test {
public:
const static inline std::vector<std::string> Names = { "Fred", "Barney", "Wilma" };
};
int main() {
std::cout << Test::Names[0];
return 0;
}

declare a array of const ints in C++

I have a class and I want to have some bit masks with values 0,1,3,7,15,...
So essentially i want to declare an array of constant int's such as:
class A{
const int masks[] = {0,1,3,5,7,....}
}
but the compiler will always complain.
I tried:
static const int masks[] = {0,1...}
static const int masks[9]; // then initializing inside the constructor
Any idea on how this can be done?
Thanks!
class A {
static const int masks[];
};
const int A::masks[] = { 1, 2, 3, 4, ... };
You may want to fixate the array within the class definition already, but you don't have to. The array will have a complete type at the point of definition (which is to keep within the .cpp file, not in the header) where it can deduce the size from the initializer.
// in the .h file
class A {
static int const masks[];
};
// in the .cpp file
int const A::masks[] = {0,1,3,5,7};
enum Masks {A=0,B=1,c=3,d=5,e=7};
you can initialize variables only in the constructor or other methods.
'static' variables must be initialized out of the class definition.
You can do this:
class A {
static const int masks[];
};
const int A::masks[] = { 1, 2, 3, 4, .... };
Well, This is because you can't initialize a private member without calling a method.
I always use Member Initialization Lists to do so for const and static data members.
If you don't know what Member Initializer Lists are ,They are just what you want.
Look at this code:
class foo
{
int const b[2];
int a;
foo(): b{2,3}, a(5) //initializes Data Member
{
//Other Code
}
}
Also GCC has this cool extension:
const int a[] = { [0] = 1, [5] = 5 }; // initializes element 0 to 1, and element 5 to 5. Every other elements to 0.

How do you declare arrays in a c++ header?

This is related to some other questions, such as: this, and some of my other questions.
In this question, and others, we see we can declare and initialise string arrays in one nice step, for example:
const char* const list[] = {"zip", "zam", "bam"}; //from other question
This can be done in the implementation of a function with no bother, or in the body of a .cpp file, outside any scope.
What I want to do is to have an array like this as as member of a class I am using, something like this:
class DataProvider : public SomethingElse
{
const char* const mStringData[] = {"Name1", "Name2", "Name3", ... "NameX"};
public:
DataProvider();
~DataProvider();
char* GetData()
{
int index = GetCurrentIndex(); //work out the index based on some other data
return mStringData[index]; //error checking and what have you omitted
}
};
But, the compiler complains and I can't seem to work out why. Is it possible to declare and initialise an array like this in one step in a class definition? Are there alternatives that are better?
Use the keyword static and external initialization to make the array a static member of the class:
In the header file:
class DataProvider : public SomethingElse
{
static const char* const mStringData[];
public:
DataProvider();
~DataProvider();
const char* const GetData()
{
int index = GetCurrentIndex(); //work out the index based on some other data
return mStringData[index]; //error checking and what have you omitted
}
};
In the .cpp file:
const char* const DataProvider::mStringData[] = {"Name1", "Name2", "Name3", ... "NameX"};
The reason you can't declare your array like that (const char* []) is that:
you can't have initializers in the class declaration, and so
the syntax const char* [] does not state how much space the compiler needs to allocate for each instance (your array is declared as instance variable).
Besides, you probably want to make that array static, since it is in essence a constant value.
This is not possible in C++. You cannot directly initialize the array. Instead you have to give it the size it will have (4 in your case), and you have to initialize the array in the constructor of DataProvider:
class DataProvider {
enum { SIZEOF_VALUES = 4 };
const char * values[SIZEOF_VALUES];
public:
DataProvider() {
const char * const v[SIZEOF_VALUES] = {
"one", "two", "three", "four"
};
std::copy(v, v + SIZEOF_VALUES, values);
}
};
Note that you have to give up on the const-ness of the pointers in the array, since you cannot directly initialize the array. But you need to later set the pointers to the right values, and thus the pointers need to be modifiable.
If your values in the array are const nevertheless, the only way is to use a static array:
/* in the header file */
class DataProvider {
enum { SIZEOF_VALUES = 4 };
static const char * const values[SIZEOF_VALUES];
};
/* in cpp file: */
const char * const DataProvider::values[SIZEOF_VALUES] =
{ "one", "two", "three", "four" };
Having the static array means all objects will share that array. Thus you will have saved memory too.