Static const variable definitions being ignored and instead initialized to 0 - c++

I have a long list of static consts that I need to use inside of a class. So rather than clutter up the class definition, I put them into a struct and defined my class to inherit the member variables of that struct like so:
/*The following code is all in the same header file in the order shown*/
struct constants{
static const double a1, a2, a3, .... ;
};
const double constants::a1 = 142314321.6536;
const double constants::a2 = 652453254.1343;
const double constants::a3 = 652134324.1234;
...(etc).
class C : constants {
//class definition...
void myFunction();
};
void C::myFunction() {
double a = a1*a2 ...;
...
}
My code compiles with no errors and runs without any errors. However, I was getting nonsense results and found that when I ran my code in the debugger, all of my static const values were zero.
What is happening that is initializing these variables to 0 but also not throwing an error at the way the variables are defined?
EDIT: I should mention, my method of preventing multiple header declarations is to use #pragma once at the top of every header file.

Related

Is there a way to avoid constexpr function used in header file from entering global scope without extra namespace for it?

I have a header file with code simply looking like this:
constexpr uint32 GenTag(const char tag[5]) { ... }
class SomeClass
{
static constexpr uint32 TAG1 = GenTag("smth");
static constexpr uint32 TAG2 = GenTag("abcd");
};
//constexpr needed for switch-case statement
The problem is that function GenTag() belongs to global scope and I would like to avoid it if possible.
I wanted to declare it inside class but it is not possible with constexpr (explanation here: constexpr not working if the function is declared inside class scope).
Does c++ have anything like "undeclare" function at the end of the header (maybe some macro tricks)? Or any other options I missed? If no better ways exist I would probably go with extra (maybe excessive) namespace, but want to ask if there are any other ideas.
There's no way to "undeclare" a function or variable in C++ (header file or not -- a header file is just included into the current translation unit). You'll need to use a namespace, or make GenTag into a macro. You can undefine macros with #undef MACRONAME.
What about defining GenTag() as a static constexpr method in an inherited struct?
If you want that GenTag() is usable only inside SomeClass, you can make it private and define SomeClass as friend inside the class containing GenTag().
I mean... something as follows
#include <iostream>
struct SomeClass;
class foo
{
static constexpr char GenTag(const char tag[5])
{ return tag[0]; }
friend SomeClass;
};
struct SomeClass : public foo
{
static constexpr char TAG1 = GenTag("smth");
static constexpr char TAG2 = GenTag("abcd");
};
int main()
{
std::cout << "Tag1: " << SomeClass::TAG1 << std::endl;
std::cout << "Tag2: " << SomeClass::TAG2 << std::endl;
// compilation error: 'GenTag' is a private member of 'foo'
// static constexpr char TAG3 = foo::GenTag("wxyz");
}
With the friend trick, you don't need to inherit from foo; but, without inheritance, you have to use it as foo::GetTag().
If anyone ever will also meet a problem like this I would recommend you to not use such constexpr in header at all but consider to declare-define it directly in and only in cpp file instead. Then you will definitely avoid unnecessary global scope pollution.
Or if there are multiple places where such constants can be used then make a separate heared for them without any classes and include that file separately from including class definition header.

How can I store values in my class private array? c++11

I have something that looks like this
class RestaurantCheck
{
private:
static const int MENU_LENGTH = 10;
static const string menu[MENU_LENGTH] = {"Gumbo", "Shrimp", etc...}
Right off the bat, I have a problem. I know I can't initialize the data in the array as it is now, so I tried this ...
class RestaurantCheck
{
private:
static const int MENU_LENGTH = 10;
static const string menu[MENU_LENGTH];
void displayMenu();
public:
void showMenu()
{
RestaurantCheck thisMenu;
thisMenu.displayMenu();
}
void RestaurantCheck::displaymenu()
{
menu[0] = "Shrimp"
menu[1] = "Gumbo"
etc...
cout << menu[0]
etc...
However I am unable to store data in the array like that as well.
How the heck am I supposed to store data in this array? As part of the assignment, the array must be a const static, it must be in private, and the displayMenu must also be private, called by a public function.
I hope what I'm getting at is clear, if not I'll try to provide more information.
EDIT:
I can not edit anything from the instructors source file. The source file is already created, and he will be using his own (provided) to test both my class file and my header file. Thus it needs to be initiated outside of sourcefile.
You are falling into the same trap as many before you. Your array is const, so it must be initialized when declared. But you can not initialize static string arrays in the class body. What do you do? You initialize it outside!
like this:
in your .h file:
static const std::string menu[10];
in your .cpp file:
const std::string RestaurantCheck::menu[10] = {"Shrimp", "Calamari", "Listeria"};
Is this what you are looking for?
You can initialize static non scalar members, but this must be done outside the class:
#include <string>
class RestaurantCheck{
static const int MENU_LENGTH = 3;
static const std::string menu[MENU_LENGTH];
};
const std::string RestaurantCheck::menu[RestaurantCheck::MENU_LENGTH] = {"Gumbo", "Shrimp", "Jar" };
note the "init line" must be present only in one file, best place is some .cpp file that is compiled to object. Here is what I mean:
restaurantcheck.h - RestaurantCheck header
restaurantcheck.cpp - RestaurantCheck implementation (best place for "init line")
main.cpp - program (where main() is located)

const array declaration in C++ header file

I have a class called AppSettings where I have an Array with a range of note frequencies. I'm getting several errors with the code below and I'm not sure what the problem is.
The error messages are:
static data member of type 'const float [36] must be initialized out of line
A brace enclosed initializer is not allowed here before '{' token
Invalid in-class initialization of static data member of non-integral type
And the code:
class AppSettings{
public:
static const float noteFrequency[36] = {
// C C# D D# E F F# G G# A A# B
130.81, 138.59, 146.83, 155.56, 164.81, 174.61, 185.00, 196.00, 207.65, 220.00, 223.08, 246.94,
261.63, 277.18, 293.66, 311.13, 329.63, 349.23, 369.99, 392.00, 415.30, 440.00, 466.16, 493.88,
523.25, 554.37, 587.33, 622.25, 659.25, 698.46, 739.99, 783.99, 830.61, 880.00, 932.33, 987.77
};
};
As the name suggests this is just a header file with some settings and values I need throughout the app.
You can't define the value of static class members within the class. You need to have a line like this in the class:
class AppSettings
{
public:
static const float noteFrequency[];
And then in an implementation file for the class (AppSettings.cpp perhaps):
const float AppSettings::noteFrequency[] = { /* ... */ };
Also, you don't need to specify the number within the [] here, because C++ is smart enough to count the number of elements in your initialization value.
This works just fine in C++11
class AppSettings{
public:
static constexpr float noteFrequency[36] = {
// C C# D D# E F F# G G# A A# B
130.81, 138.59, 146.83, 155.56, 164.81, 174.61, 185.00, 196.00, 207.65, 220.00, 223.08, 246.94,
261.63, 277.18, 293.66, 311.13, 329.63, 349.23, 369.99, 392.00, 415.30, 440.00, 466.16, 493.88,
523.25, 554.37, 587.33, 622.25, 659.25, 698.46, 739.99, 783.99, 830.61, 880.00, 932.33, 987.77
};
};
C++03 doesn't support in-class definitions of complex data like arrays of constants.
To place such a definition at namespace scope in a header file, and avoid breaking the One Definition Rule, you can leverage a special exemption for template classes, as follows:
#include <iostream>
using namespace std;
//----------------------------------------- BEGIN header file region
template< class Dummy >
struct Frequencies_
{
static const double noteFrequency[36];
};
template< class Dummy >
double const Frequencies_<Dummy>::noteFrequency[36] =
{
// C C# D D# E F F# G G# A A# B
130.81, 138.59, 146.83, 155.56, 164.81, 174.61, 185.00, 196.00, 207.65, 220.00, 223.08, 246.94,
261.63, 277.18, 293.66, 311.13, 329.63, 349.23, 369.99, 392.00, 415.30, 440.00, 466.16, 493.88,
523.25, 554.37, 587.33, 622.25, 659.25, 698.46, 739.99, 783.99, 830.61, 880.00, 932.33, 987.77
};
class AppSettings
: public Frequencies_<void>
{
public:
};
//----------------------------------------- END header file region
int main()
{
double const a = AppSettings::noteFrequency[21];
wcout << a << endl;
}
There are also some other techniques that can be used:
An inline function producing a reference to the array (or used as indexer).
Placing the definition in a separately compiled file.
Simply computing the numbers as needed.
Without more information I wouldn’t want to make the choice for you, but it shouldn’t be a difficult choice.

How can I initialize class variables in a header?

I'm writing a library where the user can define arbitrary structures and pass them to my library, which will then obtain the memory layout of the structure from a static member such structure must have as a convention.
For example:
struct CubeVertex {
// This is, per convention, required in each structure to describe itself
static const VertexElement Elements[];
float x, y, z;
float u, v;
};
const VertexElement CubeVertex::Elements[] = {
VertexElement("Position", VertexElementType::Float3),
VertexElement("TextureCoordinates", VertexElementType::Float2),
};
C++ best practices would suggest that I move the static variable and its initialization into my source (.cpp) file. I, however, want to keep the variable initialization as close to the structure as possible since whenever the structure changes, the variable has to be updated as well.
Is there a portable (= MSVC + GCC at least) way to declare such a variable inside the header file without causing ambiguous symbol / redefinition errors from the linker?
Consider a simple getter.
struct CubeVertex {
static const std::array<VertexElement, N>& GetElements() {
static const std::array<VertexElement, N> result = {
//..
};
return result;
}
//..
}
Immediate benefit: No array-to-pointer-decay.
What you could do here is using an anonymous namespace.
Wrap everything into "namespace { ... };" and you can then access CubeVertex::Elements like you normally do.
However, this creates a new instance of the static data everytime you include the headerfile, which adds to the executable's filesize.
It also has some limitations on how to use the class/struct, because you cannot call functions of that class from another file (which won't be a problem in this special case here).

Static struct in C++

I want to define an structure, where some math constants would be stored.
Here what I've got now:
struct consts {
//salt density kg/m3
static const double gamma;
};
const double consts::gamma = 2350;
It works fine, but there would be more than 10 floating point constants, so I doesn't want to wrote 'static const' before each of them. And define something like that:
static const struct consts {
//salt density kg/m3
double gamma;
};
const double consts::gamma = 2350;
It look fine, but I got these errors:
1. member function redeclaration not allowed
2. a nonstatic data member may not be defined outside its class
I wondering if there any C++ way to do it?
Use a namespace rather than trying to make a struct into a namespace.
namespace consts{
const double gamma = 2350;
}
The method of accessing the data also has exactly the same synatx. So for example:
double delta = 3 * consts::gamma;
It sounds like you really just want a namespace:
namespace consts {
const double gamma = 2350.0;
// ...
}
Except I'd try to come up with a better name than consts for it.