How to share a static variable between C++ source files? - c++

I don't know if it is possible to do this, but I have tried several ways and nothing seems to work. Basically I need to access the same static member from several files which include the same class definition.
// Filename: S.h
class S {
public:
static int foo;
static void change(int new_foo) {
foo = new_foo;
}
};
int S::foo = 0;
Then in a class definition (other .cpp file) I have:
// Filename: A.h
#include "S.h"
class A {
public:
void do_something() {
S::change(1);
}
};
And in another file:
// Filename: program.cpp
#include "S.h"
#include "A.h"
int main (int argc, char * const argv[]) {
A a = new A();
S::change(2);
std::cout << S::foo << std::endl;
a->do_something();
std::cout << S::foo << std::endl;
}
Now, I would expect the second function call to change the S::foo to 1, but the output is still:
2
Is the A.h file creating a local copy of the static class?
Thank you
Tommaso

This line:
int S::foo = 0;
needs to be in exactly one source file, not in the header. So move it from S.h to S.cpp.

Related

Declare an object inside a C++ class [duplicate]

I'm beginning to learn C++. In the IDE codeblocks, this compiles:
#include <iostream>
using namespace std;
struct A {};
struct B {
A a;
}
void hi() {
cout << "hi" << endl;
}
int main() {
hi();
return 0;
}
But this doesn't:
struct B {
A a;
}
struct A {};
int main() {
hi();
return 0;
}
void hi() {
cout << "hi" << endl;
}
It gives me the errors:
error: 'A' does not name a type
error: 'hi' was not declared in this scope
Should class/function order matter in C++? I thought it doesn't. Please clarify the issue.
Yes, you must at least declare the class/function before you use/call it, even if the actual definition does not come until afterwards.
That is why you often declare the classes/functions in header files, then #include them at the top of your cpp file. Then you can use the classes/functions in any order, since they have already been effectively declared.
Note in your case you could have done this. (working example)
void hi(); // This function is now declared
struct A; // This type is now declared
struct B {
A* a; // we can now have a pointer to it
};
int main() {
hi();
return 0;
}
void hi() { // Even though the definition is afterwards
cout << "hi" << endl;
}
struct A {}; // now A has a definition

Separating class with nested types into a header and source

There is a theme - Separating class code into a header and cpp file
It describes how to separate a class with variables and methods to .h and .cpp
But it's a simple one.
Say I have this in main.cpp
int main() {
class Filth {
int a, b;
void pra() { std::cout << a; }
class Frank {
int sacrifices;
void praisChinChin() { std::cout << "DARK LORD IS COMMINGGGGGG"; }
}
};
}
And how do I write THIS class (Filth) into a .h and .cpp so I dont get "undefined reference" and any other mistake?
And how exactly does it work (why I should write this exact code, what exactly does it do to my program)?
frank.cpp
#include "frank.h"
#include <iostream>
void Frank::praisChinChin() {
std::cout << "DARK LORD IS COMMINGGGGGG";
}
frank.h
#pragma once
class Frank {
int sacrifices = 0;
public:
void praisChinChin();
};
filth.cpp
#include "filth.h"
#include <iostream>
void Filth::pra() {
std::cout << a;
}
filth.h
#pragma once
class Filth {
int a = 0;
int b = 0;
void pra();
};
test.cpp
#include "frank.h"
int main() {
Frank f;
f.praisChinChin();
}
You are missing a semi colon at the end of class Frank.
It should compile after that.
To separate the class into .h and .cpp file you should make you function non local to the main function.
Header file might look like this.
class Filth
{
int a, b;
void pra();
class Frank
{
int sacrifices;
void praisChinChin();
};
};
And the cpp file
void Filth::pra()
{
std::cout << a;
}
void Filth::Frank::praisChinChin()
{
std::cout << "DARK LORD IS COMMINGGGGGG";
}
int main()
{
return 0;
}
I'm not sure about the "why should I write the exact code". But at the moment your code is not really doing anything. You need to create objects of your classes and call member functions, for it to have any real effect.

Global static variable initialised with a call to static class function in c++

Not sure how correctly formulate the question but here is the problem.
I have a static lib where I have the following class in a.h:
#pragma once
#include <vector>
class A{
public:
void Run() {
data_.push_back(10);
std::cout << "size: " << data_.size() << std::endl;
}
private:
static std::vector<int> data_;
};
a.cpp is as follows:
#include "a.h"
std::vector<int> A::data_;
And I have another class in b.h:
#pragma once
#include <string>
class B
{
public:
static std::string Get();
};
And b.cpp:
#include "b.h"
#include "a.h"
std::string B::Get()
{
static A a;
a.Run();
return "foo";
}
Now my main app which is using the above static lib is as follows:
#include <iostream>
#include "a.h"
#include "b.h"
static std::string var1= B::Get();
int main(int argc, char** argv)
{
A a;
a.Run();
}
Trying to understand why the output is:
size: 1
size: 1
There should be a single instance of each static data member for the entire class, so there should be a single call to A::data_ constructor.
Am I hitting "static initialization order fiasco"? I.e. data_ is not initialised before I use it, but then I should be getting the crash?
And now lets imagine my data_ holds dynamically initialised items (something none POD). How will it be destructed if at the end data_ holds one item, although I've inserted 2?
And that's what actually is happening in my real life code (it sometimes crashes during destruction of data_).
Getting rid of global static ( static std::string var1= B::Get(); ) solves the problem, but I still want to understand the under the hood problem.
The described case can be reproduced in VS2015 (the real life case is reproducible in gcc 6.2 )
Am I hitting "static initialization order fiasco"?
Most likely.
You can remove the problem by making the static data of a class available via a function call. E.g.
class A{
public:
void Run() {
getData().push_back(10);
std::cout << "size: " << getData().size() << std::endl;
}
private:
static std::vector<int>& getData();
};
std::vector<int>& A::getData()
{
static std::vector<int> data;
return data;
}
When you do that, data will be initialized when A::getData() is called the first time. It removes the static initialization order issue completely.

not declare in scope when compiled g++

This is my A.h file
class A
{
public:
void menuChoice();
void displaystartingMenu(); //EDIT
};
This is my A.cpp file
#include "A.h"
void displaystartingMenu()
{
cout<<"Please enter your choice:";
}
void A::menuChoice()
{
displaystartingMenu();
cout<<"Hello"<<endl;
}
int main()
{
A a;
a.menuChoice();
}
i tried to put
void menuChoice();
on the top of my cpp file but it still won't compile . it gives me error
In function ‘int main()’: A.cpp:112:13: error: ‘menuChoice’ was not declared in this scope menuChoice();
How do I compile : g++ A.cpp A.h
By right I don't need to even declare the function of top of the cpp because I have already declare it in my header file and I have included in my .cpp. What went wrong here?
EDIT:
Error :
In function `A::menuChoice()':
A.cpp:(.text+0x229): undefined reference to `A::displaystartingMenu()'
Option 1: Make an A instance and call that instance's menuChoice method:
#include <iostream>
class A {
public:
void menuChoice();
};
void A::menuChoice() {
std::cout << "Hello" << std::endl;
}
int main() {
A a;
a.menuChoice();
return 0;
}
Option 2: Make menuChoice a static method and call it as A::menuChoice:
#include <iostream>
class A {
public:
static void menuChoice();
};
void A::menuChoice() {
std::cout << "Hello" << std::endl;
}
int main() {
A::menuChoice();
return 0;
}
Edit: Addressing the new problem, when you tried to define A::displaystartingMenu you wrote:
void displaystartingMenu() {
// ...
}
It must be defined like this:
void A::displaystartingMenu() {
// ...
}
menuChoice is a non static member function of class A. In order to call it you need to instantiate an object A, as follows
int main()
{
A a;
a.menuChoice();
return 0;
}

error: using-declaration for non-member at class scope using std::cout

I downloaded a c++ project and was able to compile it using a makefile generated by cmake.
However when I try to add my own series of .h files in one of the .hh files of the project I start to get a million of errors, one of them being:
error: using-declaration for non-member at class scope
using std::cout;
When the .h file that contains
using std::cout is used elsewhere it works, but when added to this project it gives this error.
What can be the problem?
using std::cout;
using std::endl;
class TextManager : public FileManager {
public:
TextManager (const char * filename);
void scanFile (Image &image, Scene &scene);
void scanObjectModel (Image &image, Scene &scene);
void getImageData (Image &image);
void getMaterialData (Scene &scene);
void getLightData (Scene &scene);
void getSphereData (Scene &scene);
void getPlaneData (Scene &scene);
void getTriangleData (Scene &scene);
int getLineValue (int size);
void getLineValue2 (float (&lineNumbers) [10], Scene &scene, int &lineNumbersIndex);
void getVerticesValues (int initPos, Scene &scene);
private:
std::string line;
float fractionaryTenPowers [6];
};
Problem solved. Was the lack of a bracket to close the declaration of one of the classes that was causing it.
The error means you've done this:
struct Foo {
using std::cout;
...
};
That's not valid C++, in a class body you can only add a using-declaration for members of base classes, not arbitrary names.
You can only add using std::cout at namespace scope or inside a function body.
You can put it in the class as long as you put it under the public or private sections.
#include <iostream>
namespace CoolNamespace
{
struct AnotherReallyLongClassName
{
int a = 75;
};
struct SomeReallyLongClassName
{
int a = 42;
};
} // namespace CoolNamespace
class Widget
{
// You can't do this though!
// using ShorterName = CoolNamespace::SomeReallyLongClassName;
public:
// You can use a using statement inside of a class!
using ShorterName = CoolNamespace::SomeReallyLongClassName;
ShorterName foo;
int get_another_name()
{
return bar.a;
}
private:
// You can do it here also!
using AnotherName = CoolNamespace::AnotherReallyLongClassName;
AnotherName bar;
};
int main()
{
Widget widget;
std::cout << widget.foo.a << std::endl;
// Also, if you can reference public using statements from the class definition.
Widget::ShorterName thing;
std::cout << thing.a << std::endl;
// But you can't do this because it's private.
// Widget::AnotherName name;
return 0;
}
Indeed, check if you have one open bracket in one of the member functions in the class declaration.
I did this in .h file;
class foo{
void cat();
void bar{
void dog();
}
in .cc file I defined the member functions
void foo::cat(){
std::cout<<"This is cat"<<std::endl;
}
void foo::bar(){
std::cout<<"hello"<<std::endl;
}
void foo::dog(){
std::cout<<"meow"<<std::endl;
}
But notice I used { instead of; for member function bar in .h file. That's causing the error. (At least for me).