I have a problem with my Qt(c++) class.
Code:
SharedVariables.h
class SharedVariables
{
private:
QString TextoPesquisa;
bool LoginEfectuado;
public:
SharedVariables();
QString getTextoPesquisa();
void setTextoPesquisa(QString TxtPesquisa);
bool getLoginUtilizador();
void setLoginUtilizador(bool UtilizadorComLogin);
};
SharedVariables.cpp
QString ShareVariables::getTextoPesquisa()
{
return TextoPesquisa;
}
void ShareVariables::setTextoPesquisa(QString TxtPesquisa)
{
TextoPesquisa = TxtPesquisa;
}
bool ShareVariables::getLoginUtilizador()
{
return LoginEfectuado;
}
void ShareVariables::setLoginUtilizador(bool UtilizadorComLogin)
{
LoginEfectuado = UtilizadorComLogin;
}
Then to have access to the functions in my 2 (or more) cpp's, I use this :
File1.cpp (the one who writes)
SharedVariables e1;
e1.setTextoPesquisa("StringHERE");
File1.cpp (the one who reads)
SharedVariables e2;
qDebug() << e2.getTextoPesquisa();
The problem is that when the e2 is initialized my QString TextoPesquisa becomes empty again, And i don't know who to solve this problem, since I want that the values stay the same so I can access everywhere with this functions.
The variable need to be static:
class SharedVariables
{
private:
static QString TextoPesquisa;
Also make sure you declare TexttoPesquisa in cpp file:
QString SharedVariables::TextoPesquisa;
Because static variables aren't bound to particular class instance, they need their own memory location.
e2 is empty because you are using two different instances of the same class.
You need to create a SharedVariables object (on your main for example) and then use it on your various classes in .cpp files.
Related
I have many function definitions which I have placed in different cpp files with function declarations in their respective .h files.
I have a set of a variables which I have placed in a .h file. These variables need to modified by different functions. I am using static to keep the changes from each function, but I heard it is a bad coding practice. How else to do it ? For eg -
variables.h
class variable{
static int x;
static int y;
};
function1.h
class function(){
public:
void function1();
}
similar for function 2
function 1.cpp
void function1(){
// does something with x and y (used as (variable::x=2;variable::y=3)
}
function2.cpp
void function2(){
// does something with x and y (used as variable::x+=2;variable::y+=2)
}
main.cpp
int variable::x;
int variable::y;
int main(){
obj.function1(); (obj is object of function1 class)
obj2.function2(); (obj2 is object of function2 class)
cout << variable::x << variable::y << endl;
}
I was was using different objects in different cpp files but changes in one function were not reflecting in other. How it use it please help?
You can simply move these variables into another class:
struct Shared {
int x;
int y;
};
Now you can pass an instance to this class as parameter to your function, this is called dependency injection:
void foo(Shared& shared) {
shared.x = 4;
shared.y = 2;
}
This is better because you don't have any global state anymore. You could use the function multiple times independent from each other by referencing a different instance of the Shared class.
It is very common to take this a step further by "injecting" the instance in the constructor of that class. This is helpful if the instance of that class should always reference the same instance:
struct Foo {
Shared& m_shared;
Foo(Shared& shared)
: m_shared(shared)
{
}
void foo() {
m_shared.x = 4;
m_shared.y = 2;
}
};
Yes, as you mentioned using static variable for this purpose is kind of anti-pattern. A better pattern (without knowing the background of the application) is using a composition pattern. If your functions f1() and f2() are in classes C1 and C2, you would e. g. create an additional data object D1 (with the variables in question), and inject and object of D1 in the constructor of C1 and C2, so both classes operation on a data object. There are also other solutions to this situation, but I guess thats the most general. Google for C++ Design Pattern to find more general patterns.
You can use smart pointers for global objects
struct MyGlobal
{
std::shared_ptr<Core> core;
MyGlobal(){ core=std::make_shared<Core>(); }
void changeVariableX(int X)
{
core->X = X;
}
};
You can move, copy, do whatever you want with MyGlobal instances and they still point to same core item. Just make sure all of them are populated from same instance like this:
int main()
{
MyGlobal global;
auto something = useSomeFunctionWith(global);
auto somethingElse = useAnotherFunctionWith(global);
...
// use something and somethingElse to change X, both point to the same X
}
If functions will not be thread-safe then you should add a lock-guard into changeVariableX method.
I am working with a project that is largely not of my creation, but am tasked with adding in some functionality to it. Currently, there is a device class that has a member variable that is responsible for storing information about a storage location, setup like this:
device.hpp
class device {
public:
// Stuff
private:
// Stuff
StorageInfo storage_info_;
// Even more stuff
}
StorageInfo.hpp
class StorageInfo {
public:
void initializeStorage();
void updateStorageInfo();
int popLocation();
int peakLocation();
uint16_t totalSize();
uint16_t remainingSize();
// More declarations here
private:
//Even more stuff here
}
I am tasked with implementing a different storage option so that the two can be switched between. The information functions that this new storage option has would be the same as the initial storage option, but the implementation in retrieving that information is vastly different. In order to keep things clean and make it easier to maintain this application for years to come, they really need to be defined in two different files. However, this creates an issue inside of device.cpp, and in every single other file that calls the StorageInfo class. If I create two separate member variables, one for each type of storage, then not only will I need to insert a million different ifelse statements, but I have the potential to run into initialization issues in the constructors. What I would instead like to do is have one member variable that has the potential to hold either storage option class. Something like this:
StorageInfoA.hpp
class StorageInfoA: StorageInfo {
public:
void initializeStorage();
void updateStorageInfo();
int popLocation();
int peakLocation();
uint16_t totalSize();
uint16_t remainingSize();
// More declarations here
private:
//Even more stuff here
}
StorageInfoB.hpp
class StorageInfoB: StorageInfo {
public:
void initializeStorage();
void updateStorageInfo();
int popLocation();
int peakLocation();
uint16_t totalSize();
uint16_t remainingSize();
// More declarations here
private:
//Even more stuff here
}
device.hpp
class device {
public:
// Stuff
private:
// Stuff
StorageInfo storage_info_;
// Even more stuff
}
device.cpp
//Somewhere in the constructor of device.cpp
if(save_to_cache){
storage_info_ = StorageInfoA();
} else {
storage_info_ = StorageInfoB();
}
// Then, these types of calls would return the correct implementation without further ifelse calls
storage_info_.updateStorageInfo();
However, I know that cpp absolutely hates anything with dynamic typing, so I don't really know how to implement this. Is this kind of thing even possible? If not, does anyone know of a similar way to implement this that does work with cpp's typing rules?
You are on the right track, but you have to learn how to use polymorphism. In your example, you need the following fixes:
In the base class, make all functions virtual, and add a virtual
destructor:
class StorageInfo {
public:
virtual ~StorageInfo(){}
virtual void initializeStorage();
//...
};
Make your inheritance public:
class StorageInfoA: public StorageInfo {
Instead of holding StorageInfo by value, hold it in a smart pointer:
class device {
private:
std::unique_ptr<StorageInfo> storage_info_;
};
device constructor will look like
//Somewhere in the constructor of device.cpp
if(save_to_cache){
storage_info_ = std::make_unique<StorageInfoA>();
} else {
storage_info_ = std::make_unique<StorageInfoB>();
}
Finally, you will use it like an ordinary pointer:
storage_info_->updateStorageInfo();
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)
I have the following problem (just learning OOP style C++): I have 3 classes:
app
objectManager
object
The app class sets up startup variables and creates an instance of objectManager. It tells objectManager to load values from different files and to precalculate some data in a vector what will be required for each object.
My problem is the following: I would like to use a precalculated vector accessable for each object. I don't understand how can I possibly access this variable from the objects, as they know absolutely nothing about the manager's instance.
I've read about singletons but I have no idea how should I implement it.
I've read about static data members but AFAIK it seems that I still have to somehow connect to the objectManager instance, so it doesn't help me.
I've tried global variables (I know...), but ended up with compiling errors.
I've tried to put static variables outside of a class definition in objectManager.h (is it a global case?), and I ended up with something strange:
I can access the variables from all parts of the program what includes objectManager.h, but it's value is different/uninitialized in different classes.
objectManager.h
#pragma once
#include "Object.h"
static int xxxtest;
class objectManager
{
objectManager.cpp
xxxtest = 123456;
cout << xxxtest << endl;
-> 123456
while in object.cpp or app.cpp (after)
cout << xxxtest << endl;
-> 0
Can you explain to me what is happening here?
Can you recommend me a simple and clean way of organizing such a program, while making a precalculated variable accessable to other parts of the program?
Static class variables are in fact the solution.
Static variables in classes need to be declared in the CPP file, right after the include.
Header:
class Class {
static int staticVariable;
static void staticFunction();
//...
};
CPP:
int Class::staticVariable = 5;
Do that, and all Object instances have access to the static variable (if it's private) and all members of the entire Program can access it (if it's public) by stating:
int Value = Class::staticVariable;
I hope this helps shed some light.
Ah yeah, I used the code from http://de.wikibooks.org/wiki/C++-Programmierung:_Statische_Elemente_in_Klassen (Page is in German) as Reference.
To get back to your problem, that would mean:
Header:
class objectManager {
static std::vector<double> Precompiled;
};
CPP:
std::vector<double> Precompiled; //Initialized automatically.
Since you only intend to create one objectManager, it is a candidate for a singleton or a regular global. As a global, you could define a header file like this:
// in object_manager.hpp
class App;
class ObjectManager;
class ObjectManagerImpl;
ObjectManager & objectManager ();
class ObjectManager {
friend ObjectManager & objectManager ();
friend class App;
std::unique_ptr<ObjectManagerImpl> impl_;
ObjectManager ();
void read_files (std::string file1, std::string file2);
public:
std::vector<int> & precomputed ();
//...
};
And in your source file, you could have something like:
// in object_manager.cpp
class ObjectManagerImpl {
friend class ObjectManager;
std::vector<int> precomputed_;
//...
};
ObjectManager::ObjectManager () : impl_(new ObjectManagerImpl) {}
void ObjectManager::read_files (std::string file1, std::string file2) {
//...
}
std::vector<int> & ObjectManager::precomputed () {
return impl_->precomputed_;
}
//...
ObjectManager & objectManager () {
static ObjectManager instance;
return instance;
}
Now, in the source file of your object, you would include the header file for objectManager, and access the vector through the accessor.
// in object.cpp
//...
std::vector<int> &precomputed = objectManager().precomputed();
Suppose I have a class called Poem.
class Poem{
virtual void recite() = 0;
}
And I have hundreds of .cpp and .hpp files which describe a subclass, like the following
class TheRaven : public Poem{
void recite() { std::cout << "NEVERMORE!" << endl; }
}
And the likes. And in the main function, I'd like to be able to just iterate through every single possible Poem subclasses and call their recite() function. So I made a class:
class PoemRegistry{
std::map<std::string, Poem*> poems;
PoemRegistry& getGlobal(); // returns a static global registry
void register(const std::string& poemname, Poem * thepoem);
};
And then for each poem subclass .cpp file, I put the following.
class TheRavenRegistor{
TheRavenRegistor(){
PoemRegistry::getGlobal().register("theraven", new TheRaven());
}
}
TheRavenRegistor registor();
ninja edit: I put the global class there, forgot about it
Making it easy, I make a shortcut with #define and templates.
Now, the question is, I just heard about the static class initialization fiasco. I suppose this will be immune against it, or is there something I am definitely missing here? Or is there something more elegant that can be used for this purpose?
This is an example for the Singleton design pattern. Don't use a static global, since the initialisation order is undefined across compilation units.
Instead use something like this:
PoemRegistry& PoemRegistry::getGlobal()
{
static PoemRegistry theRegistry; // construction guaranteed when first call
return theRegistry;
}
Make the getGlobal() method static:
class PoemRegistry
{
public:
static PoemRegistry& getGlobal();
...