Is there any way, in C++, to define nested macros/constants within a class, in a similiar fashion to nested typedefs, or a method to acheive similiar functionality? The motive is generally for the macros to be used by templates.
class SomeClass
{
public:
#define SomeConstant 123
};
int x=SomeClass::SomeConstant;
Ofcourse, static const members can do the job, but those are physical variables, while I'm looking for a simple macro-like behavior.
You can't do what you want with macros. Macros have no concept of scoping.
But for simple int values you can do what you want with enums.
class SomeClass
{
public:
enum {
SomeConstant=123
};
};
int x=SomeClass::SomeConstant;
A fully scoped name for the value, but no space taken for it, even in debug builds - you couldn't take its address if you wanted to.
Const values declared and defined in-place are exactly what you need here: the compiler can and will optimise them away completely so they end up being exactly the same as using the #define in the first place, but with the benefits of strict scoping.
class SomeClass {
public:
static const int someValue = 10;
};
This doesn't take up any extra space - no memory is allocated to store "someValue". You can prove this: if you try and use the "someValue" as a real object (ie you try and get its address), then the linker will tell you it's undefined.
Macros completely ignore scope - they are expanded before the C++ compilation. You just can't do that.
Use of static const often leads to no variable being allocated - the compiler treats it as a constant.
Macro pre-processors generally don't have any idea of language context; thus they don't know what a "class" is making "nesting inside a class" not make sense in the first place.
For what you want, either use static const, or use the full name (assuming the preprocessor allows colons in macro names, not 100% sure on that) - though it won't allow you to inherit the constant on derived classes:
#define SomeClass::SomeConstant 123
You can do this with templates:
template < int someConstant = 123 > class SomeClass
{
public:
void outputConstant() { cout << "We think the answer is:" << someConstant; }
}
But that isn't precisely what you want because you have to declare an instance of the class as:
int main(int argc, char *argv)
{
SomeClass<123> myInstance;
}
I know others have explained the bit about macros, but allow me to add: #define is processed by the pre-processor, not the compiler. In the standard is a section called "translation phases" which explains this in more detail, but for your question the point is that macros are evaluated before the class is even compiled, and the scope at which the #define occurs is not known.
The authoritative book on this subject (programming with templates during the compile stage) is Modern C++ Design: Generic Programming and Design Patterns Applied, by Andrei Alexandrescu.
I don't understand your objection to using a static const.
It will not effect the size of your class, and the compiler will optimise to achieve what you think you'd get from a macro.
"Static members are physical variables".
What's against this? The only reason to object to this would be memory usage. But since the member is static, the memory would only be occupied once with the intended content.
On the contrary, with a macro, the contend would be present at every single usage location in the binary.
EDIT:
In case the variable is of an integral type, smaller than a pointer, it's probably best to define the constant in the class declaration. Optimizing compilers can then inline the value in the calling code, just like for a macro.
Related
So I have this problem for a while now. I just couldn't find the answer to the question. Why do I have to give the data type twice while using static variables inside a class?
Here's an example:
#include <iostream>
class Test{
public:
static int test;
};
//right here is the point of confusion
int Test::test = 10;
int main(){
Test test;
std::cout << test.test << "\n";
}
As you can see from my program above I had to initialize the variable this way. But what about the duplicate data type specification? Why did I have to write the "int" data type twice? Once already in the class and then again? What is the underlying reason? Thanks for any help in advance.
You don't 'have to' duplicate as long as you provide the type somehow. Grammar requires a type there that cannot be auto (which is not type, but usually people expect to be able to write it in place of a type), but you can still let the compiler deduce it:
#include <iostream>
class Test{
public:
static int test;
};
//right here is the point of confusion
decltype(Test::test) Test::test = 10;
int main(){
Test test;
std::cout << test.test << "\n";
}
If you don't like duplicating type name, you might write a macro for it.
Why did I have to write the "int" data type twice?
Because there are 3 components of a simple-declaration, namely attributes, specifiers and declarators and a definition(like the one you provided) is also a declaration so it has to follow these rules. Now, the second of these component, specifier indicate the type, storage class or other properties of the entity that is being declared and is not optional.
This means that when providing the definition for the static data member, you still need to provide the type-specifier according to the grammar. This also means that you can use decltype(Test::test) instead of int when defining the static data member outside the class.
The point is that the current grammar requires us to specify the type when defining.
If you are asking about the rationale, then nobody (except probably Bjarne himself) knows for sure. Such things were rarely publicly discussed or written down when the language was conceived. But if I had to guess, I'd say that it is to make the language rules simple and get the language out of the door faster. Every declaration needs a type. That's essential in the formulation of the grammar. If you change such a fundamental thing willy-nilly, you risk opening a huge can of worms.
I've been learning C++, and I've come across static variable (I have prior knowledge from C89), and in the resource i'm using, they've declared a static variable in a class such as:
class nameHere
{
public:
static int totalNum;
}
int nameHere::totalNum = 0;
int main()
{}
For Example.
What I don't understand is that, since I've already declared that the static variable is an integer in the class definition, why do I need to also declare it as an integer outside of the class definition?
Would it not make sense to simply initialise it like so:
nameHere::totalNum = 0;
int main()
{}
Is there a particular reason or simply a convention of C++?
Thanks for all the help!
This would (probably) make the language even more difficult to parse (and it's already almost insanely difficult to parse anyway).
As it is, the datatype (int, long, my_class, whatever) tells the compiler that what it's seeing is the beginning of a declaration (which, in this case, is also a definition). Without that, the compiler would have a rather more difficult time sorting things out.
In the specific case of things at global scope, it wouldn't be that bad, because at global scope about all you can have is a series of declarations. At any other scope, however, things would be more difficult (and having one rule at global scope, and another elsewhere would be ugly indeed).
In C++11 you can simply initialize the variable inside the class:
class nameHere
{
public:
static const int totalNum = {0};
}
There is a difference between a definition and a declaration.
While the static variable in the class has been declared, it has not been defined. The One Definition Rule, explains declarations and definitions and states
In any translation unit, a template, type, function, or object can have no more than one definition. Some of these can have any number of declarations.
Therefore, the full type of the object must be used when declaring the variable.
Before switching to C++, we found the initialization language element in Delphi extremely useful. It allowed you to have code in each unit which would be called when the program was started, so you could initialize various elements of that unit.
This does in our opinion make things easier and helps to keep the code clean.
So why is there no initialization and finalization in C++?
What are our options for replacements of this language feature in C++?
The equivalent C++ feature is constructors and destructors for file-scope/global objects. For instance:
#include <iostream>
using std::cout;
struct X {
X() { cout << "X::X()\n"; }
~X() { cout << "X::~X()\n"; }
};
static X x;
int main() { cout << "main()\n"; return 0; }
will output
X::X()
main()
X::~X()
when run.
It is generally considered unwise to use this feature, because you have no control whatsoever over the order in which these constructors and destructors are executed, which means things may get initialized before their dependencies, producing hard-to-debug crashes.
In C++ constructor/destructor pairs are generally used for this sort of thing. Be careful when using static objects, however. Two things you should read if you want to do this:
What's the "static initialization order fiasco"?
How do I prevent the "static initialization order fiasco"?
Question 1: why isn't there a keyword?
No-one apart from Stroustrup or the committee members can really answer why C++ is how it is, but we can speculate, probably that it wasn't considered important enough for a keyword. The C++ standard does talk about order of initialization, such as for objects but the order is not strictly defined and left to the implementation. Here's one quote (3.6.2/3):
It is implementation-defined whether
or not the dynamic initialization
(8.5, 9.4, 12.1, 12.6.1) of an object
of namespace scope is done before the
first statement of main. If the
initialization is deferred to some
point in time after the first
statement of main, it shall occur
before the first use of any function
or object defined in the same
translation unit as the object to be
initialized
Question 2: how to achieve the equivalent of the Delphi initialization and finalization keywords?
There are two options. The first has been mentioned by other posters and I don't want to copy their answers: declare an object in a certain scope (translation unit or namespace) and its constructor and destructor will be called 'sometime'; do work there.
Note that the order of this is implementation-defined, so you're already in uncertain territory.
The second option is also compiler dependent. You're using Delphi, so am I right in thinking you're using C++ Builder to compile your C++ code? If so, C++ Builder and some other compilers support the #pragma startup and #pragma exit pragmas. These pragmas call a method at a certain time when your program is starting up or shutting down.
Personally I find this a neater solution, for two reasons:
It specifies exactly when something
will occur and I can see it written
down in code
It allows you to call a
function, instead of using a
constructor or destructor. This is
aesthetically cleaner and lets you write, say,
initialization() and finalization() methods which
perform your work. This probably gets you as close to the Delphi syntax as you can get.
You can use these pragmas to call a procedure (which takes no parameters and returns void) and also optionally specify when it should occur, using a number between 64 and 255. You need to do this only if the order of initialization or finalization matters. A higher number is called first and priorities of 0-63 are reserved. For example:
void initialization(void) { foo = 3; bar = 5; /* Do useful work here */ }
#pragma startup initialization 200
void finalization(void) { foo = 0; bar = 0; /* Do useful work here */ }
#pragma exit finalization 200
The call chain is managed by the linker and you can run into issues if you use more compiler-specific constructs, such as weak packaging, but in general this is the technique I would recommend.
Class have constructors and destructors that you can use to intialize and clean up.
I think the closest you get to "code units" in C++ is classes.
Write a class with a constructor (initialization code) and a destructor (finalization code). Declare a singleton instance of this class; the constructor will be called at startup, and the destructor before the program shuts down.
Typically, it's viewed as a code smell in C++ to have global state that needs construction or destruction, and even if you did have this, you would just declare a class that does this in it's constructor and define a file-global instance of it.
In C++ you call the constructor (equivalent to your destructor) the same name of you class and the destructor the same name of you class, prefixed with tilde (~):
Class Point {
public:
Point() { }
~Point() { }
}
The closest feature C++ has to what you are use to is static variables (specifically, static member variables).
// A.h
class A
{
public:
private:
static int someValue;
};
// A.cpp
int A::someValue = 2;
The static variable is initialized at program startup. There is no automatic "finalization" procedure for static members (you would have to write your own cleanup function and call it).
I know how to initialize a static member that's not an integer, but I'm wondering, what is the rationale behind the syntax for this? I'd like to be able to just put the value in the class, like you can with an integer member, a la:
class A {
static const int i = 3;
};
I realise this could mean more rebuilding if I change the value since it's a change in the header - but in some cases that's pretty unlikely - and just as bad as changing a #define in the header anyway.
It doesn't seem like something that would be terribly hard for the compiler to understand. Are there technical reasons why it works the way it does? Or is it just a case of the compiler enforcing the good practice of separating the implementation from the definition?
Because that is the class declaration. You don't have any object yet.
You need to actually define the value somewhere --- somewhere specific.
Since it is static it's actually taking up space somewhere. But, since the .H file which has that declaration can be #included in many source files, which one defines holds the actual space it is using? Having the compiler automatically define the space in every object file and having the linker sort it out would be a violation of the "One Definition Rule".
A static class member has linkage, so it needs to be in a source file. Just because you declare it const doesn't mean it really can't change (please look up volatile for example).
This might help you:
class A {
enum { i = 3 }; // use an enum to set a constant value in the class declaration
void f() { int k = int(i); }
}
I have a few questions about the static keyword in C++ (and probably with other languages as well.) What is the purpose of declaring a function as static?
void static foo(int aNumber) {
... }
How about a static inline function?
void static inline foo(int aNumber) {
... }
Is there any benefit to using the static keyword with a function, and do those benefits apply to class functions as well?
I realize some datatypes like structs and arrays have to be static when compiling with an older compiler, but is there any point when using a new ANSI-C++ compiler (like MS VC++ 2008)? I know that using a static variable inside a loop saves time by keeping the data in memory and not reallocating memory every loop iteration, but how about when a variable is declared only once, like at the top of a header file or within a namespace?
Depends on Context:
Like many things in C++, static means different things depending on its context.
It's very common in C++ for the same word to mean different things depending on its context.
For example:
* is used for multiplication, dereferencing a pointer, and creating pointers.
& is used to get the address of variables, to declare a reference, and as a bitwise AND operator.
Global use of static:
If you declare a function or variable as static outside of a class and in global scope, it is specific to only that file. If you try to use that variable or function in a different file (via a forward declaration) you will get a linking error.
Example:
a.cpp:
static void fn()
{
cout<<"hello a!"<<endl;
}
b.cpp:
void fn();
void gn()
{
fn();//causes linking error
}
This feature allows you to use a function that no other file will ever see, that way you don't cause possible linker errors of a symbol defined multiple times. The preferred method to do this is with anonymous namespaces though:
a.cpp:
namespace
{
void fn() // will be static to a.cpp
{
cout<<"hello a!"<<endl;
}
}
Inside of a class use of static:
If you declare a function or variable as static inside of a class (or struct), it is a class function or class variable. This means that there is only one for that whole class. A class function can only use class variables. A class variable is shared amongst all instances of that class.
class C
{
public:
static void fn()
{
y = 4;//<--- compiling error
// can't access member variable within a static function.
}
int y;
}
This is a great feature to use if you have something that is specific to the class of your objects, but not specific to an instance.
Inside a function use of static:
If you declare a variable as static inside of a function, you can consider that the variable value will persist upon calls. It will only be initialized once.
Example:
//Will print 0, then 1, then 2, ...
void persistentPrintX()
{
static int x = 0;
cout << x << endl;
x++;
}
I personally try to avoid this, and you probably should to. It is not good to have global state. It is better to have functions that given the same input guarantees the same output.
Just like in the English language:
The concept of context sensitive meaning is not specific to C++, you can even see it in the English language.
I am going to screen a movie (Means showing the movie)
The screen on the TV is broken (Means a part of the TV)
Other meanings in other programming languages:
Depending on the programming language there can be a different meaning, but the first thing most people think of when you say static is a class variable/function vs a member variable/function.
I hang around on the ##c++ irc channel on irc.freenode.net and I really like the clarification on static that the bot nolyc is programmed to give. I quote word for word:
When used inside a function, the
static keyword indicates that a
variable is shared between all calls
of the function. When used inside a
class, it indicates that the variable
or function is a member but is not
tied to a specific instance. When
used inside a namespace, it specifies
internal linkage.
I hope that clears things up. I haven't answered all your questions. I would say that you should use the static keyword to do what it was intended to do. Use it as a tool to accompolish your task, if it is the right one for the job. As far as benefits go, I wouldn't worry. If you need to optimize, then think about those effects if there is no other resort.
I hope this helps.