Hello guys i have static problem with my class:
class Monster
{
private:
static const bool hard;
//more staff here
};
I know that i can initiate it like const bool Monster::hard
But I want to know if i can initiate based on users input
Something like If(wantToBeHard) hard = true;
This means it must be in a method or something right?
There is any way to do this?
You can create a normal function (not a non-static member function) which asks for input from the user and returns a bool value:
bool AskUser()
{
....
}
Then simply use the return value of that function to initialize your static member.
const bool Monster::hard = AskUser();
Just to clear things up, here is a complete, compileable example:
#include <iostream>
#include <string>
bool AskUser();
class Monster
{
public:
static bool IsHard() { return hard; }
private:
static const bool hard;
};
int main()
{
if (Monster::IsHard())
std::cout << "it is hard\n";
else
std::cout << "it is not hard\n";
}
bool AskUser()
{
std::cout << "hard? ";
std::string input;
std::getline(std::cin, input);
return input.size() && input[0] == 'y';
}
const bool Monster::hard = AskUser();
If you want more control over when this initialization happens, you will have to drop your requirement for const. It shouldn't really be a problem though, as long as the member is private, you can still have complete control over whether it is changed. e.g.
class Monster
{
public:
static void SetHard()
{
static bool hard_is_set = false;
if (hard_is_set)
return;
hard_is_set = true;
hard = AskUser();
}
private:
static bool hard;
};
bool Monster::hard;
One possible problem here is that it is possible to call the SetHard function outside of main (e.g. in the initialization of another static object), if that happens, it may access the static member before it is actually created, resulting in undefined behavior. (static objects are tricky things and should be treated with care). So don't do that.
Related
I have a class that has a few static functions that can be called even if there is no instance of that class. There is also a method init() that I use to set some variables. This method is not static thus it needs an instance. Now if this was done I want the static methods to behave differently. Sort of like:
static foo(){
if(noInstance()){
doA();
}else(){
doB();
}
}
Is this even possible? Or a bad idea and should just make the user call different methods if there is an instance?
Thanks
EDIT
It sounds weird but this is my use case:
class A{
public:
static inline bool hasInstance = false;
int data;
static int getData(){
if(hasInstance){
return data; // Can't do this from a static function
}else{
return 0;
}
}
};
I know that I cant access the data from a static function beacuse there is no this pointer. I'm coding a library and I want the user to be able to use the static method if he dosen't want an instance but if there is an instance it should make use of the data of its instance.
If had an idea but I don't know wether that's good style:
static int getData(A *ref){
if(ref != nullptr){
return data;
}else{
return 0;
}
}
I'd glad to hear from someone with more experience wether I should do that.
I think you can use a static variable, let it be named count. You initialize count with 0, and every time you create an instance of that class, you increment count. If count is 0, that means you did not created any instance, therefore you can't use some methods.
I'm coding a library and I want the user to be able to use the static method if he dosen't want an instance but if there is an instance it should make use of the data of its instance.
In general, free functions are recommended rather than member functions (gotw). It is actually rare to have good reasons to make a static function a member function. It would need to be a member if it would need access to privates of the class, but that doesnt seem to be the case here and then it still could be a friend function.
Let's look at your approach:
static int getData(A *ref){
if(ref != nullptr){
return data;
}else{
return 0;
}
}
You probably meant to write ref->data;, also I guess you are not merely returning the value of the member. That would be of little use, because If I have an instance I can get my hands on x.data without needing to call getData. And I suppose 0 is just a placeholder for someother value that you have there in the real code.
I am going a bit subjective now...
If I was a user of your library, I would want to know if getData returns data from one of the objects I did create or something else. Having one and the same function that does both would confuse me. I don't like pointers and I am scared of nullpointers, so if you force me to write
getData(nullptr);
this would not make me happy. I would like to have two different functions:
int getData() { return 0; }
int getData(const A& x) { return x.data; }
If I have no instance, I can call the first, if I have one I can call the second.
Not sure what is your final goal, but I would recommend reconsidering your design, because this static/hasInstance behavior smells.
Anyway, here is what you need:
using namespace std;
#include <iostream>
class MyClass
{
private:
static bool hasInstance;
public:
MyClass()
{
hasInstance = true;
}
static void foo()
{
if (hasInstance) {
std::cout << "I have an instance\n";
}
else {
std::cout << "No instance\n";
}
}
};
bool MyClass::hasInstance = false;
int main () {
MyClass::foo();
MyClass a;
a.foo();
MyClass::foo();
return 0;
}
EDIT:
Don't use it in real code. If you just curious, you can do almost everything in C++, so you could pass the object sometimes, it's dirty and ugly, but just for the demo:
using namespace std;
#include <iostream>
class MyClass
{
private:
int someVariable;
public:
MyClass()
{
someVariable = 42;
}
static void foo(MyClass *obj = nullptr)
{
if (obj) {
std::cout << obj->someVariable << std::endl;
}
else {
std::cout << "No instance\n";
}
}
};
int main () {
MyClass::foo();
MyClass a;
a.foo(&a);
MyClass::foo(&a);
return 0;
}
I have class CStudent and class CStudentGroup which has one member set<CStudent>. I populate the set of an object from the class CStudentGroup. I want to iterate this set and print via the getter of the CStudent class the points of all the students in the set. I do this by assigning the set to a new one. Then I iterate the set with an iterator it. However the compiler gives an error *the object has type qualifiers that are not compatible with the member function CStudent::getP; object type is const CStudent* I would like to ask how can I do this? Thank you in advance.
#include <iostream>
#include <string>
#include <set>
using namespace std;
class CStudent {
string m_strFN;
int m_iPoints;
public:
void setP(int p) {
m_iPoints = p;
}
void setFN(string f) {
m_strFN = f;
}
int getP() {
return m_iPoints;
}
string getFN() {
return m_strFN;
}
CStudent() {
m_strFN = "123456789";
m_iPoints = 70;
}
CStudent(const CStudent& stud) {
m_strFN = stud.m_strFN;
m_iPoints = stud.m_iPoints;
};
CStudent(int p) {
m_iPoints = p;
}
};
class CStudentGroup {
set<CStudent> m_setStudents;
public:
CStudentGroup(const CStudentGroup& grp) {
m_setStudents = grp.m_setStudents;
};
CStudentGroup(set<CStudent> st) {
m_setStudents = st;
}
CStudentGroup() {
CStudent s1(50), s2, s3(s2);
m_setStudents.insert(s1);
m_setStudents.insert(s2);
m_setStudents.insert(s3);
}
set<CStudent> gets() {
return m_setStudents;
}
};
int main()
{
CStudentGroup group;
set<CStudent> stt = group.gets();
for (set<CStudent>::iterator it = stt.begin(); it != stt.end(); it++) {
cout << it->getP() << endl;
}
}
std::set stores keys as constant value, as a change of a key can be a cause of change to its position in red-black tree (typical std::set implementation).
In other words, your CStudent object are considered const or unchangeable.
It's possible to problem here using std::set::const_iterator as a type of iterator inside the loop in combination with std::set::cbegin() and std::set::cend() calls.
Another possible solution is to use foreach-loop:
for (CStudent const& student : stt)
std::cout << student.getP() << '\n';
Moreover, you would need to change CStudent::getP() declaration to be a constant method.
Objects inside a std::set are always const. That is to protect them, in case you decide you change any key field, the sorting order changes and the set invariant is broken.
So basically the set<CStudent>::iterator is a const_iterator and you get a const CStudent& reference. Since your CStudent::getP is not a const member function, you cannot use it.
Solution, make it const:
int getP() const {
return m_iPoints;
}
Naturally, you want to mark as const any function that does not change the contents of your object, not only the ones std::set requires you to do so. This is sometimes called const-correctness and is always a good practice.
I have a (parent) class named Alma with the (virtual) function Getwidth() and two derived class of Alma, named Birs (with the special function Getheight()) and Citrom (with the special function Getdepth()). I want to declare an object - named Attila - which type is Birs or Citrom depending on a bool. Later, I want to use the common function Getwidth() and also the special functions (depending the bool mentioned).
My (not working) code:
/*...*/
/*Classes*/
class Alma{
public: virtual int Getwidth() = 0;
/*ect...*/
}
class Birs: public Alma{
int Getwidth(){return 1;}
public: int Getheight(){return 2;}
/*ect...*/
}
class Citrom: public Alma{
int Getwidth(){return 3;}
public: int Getdepth(){return 4;}
/*ect...*/
}
/*...*/
/*Using them*/
void Useobjects(){
/*Create object depending on bool*/
if(b00lvar){
Birs Andor();
std::cout<<Andor.Getwidth()<<" "<<Andor.Getheight()<<std::endl;
}else{
Citrom Andor();
std::cout<<Andor.Getwidth()<<" "<<Andor.Getdepth()<<std::endl;
}
/*Using the common part of object*/
std::cout<<Andor.Getwidth()<<std::endl;
/*Using the special part of object*/
if(b00lvar){
std::cout<<Andor.Getheight()<<std::endl;
}else{
std::cout<<Andor.Getdepth()<<std::endl;
}
/*ect...*/
}
This is a classic case of polymorphic object handling. Just make sure you are familiar with that concept as well with pointers and references.
What you need is something looking like:
Alma* Andor;
if(b00lvar){
Andor = new Birs();
std::cout<<Andor->Getwidth()<<" "<<Andor->Getheight()<<std::endl;
}else{
Andor = new Citrom();
std::cout<<Andor->Getwidth()<<" "<<Andor->Getdepth()<<std::endl;
}
Next use dynamic_cast to get back to the derived types and finally of course do not forget to delete the object. But first read about those concepts.
You cannot define a single object whose type is this or that, depending on something else. C++ doesn't work this way. C++ is a statically-typed language. This means that the type of every object is determined at compile time. Other languages, like Perl, or Javascript, are dynamically-typed, where the type of an object is determined at runtime, and a single object can be one thing, at one point, and something else at a different point.
But C++ does not work this way.
To do something like what you're trying to do, you have to refactor the code, and work with the virtual superclass. Something like this:
void UseObject(Alma &andor)
{
/*Using the common part of object*/
std::cout<<andor.Getwidth()<<std::endl;
/*Using the special part of object*/
/* This part is your homework assignment */
}
void Useobjects(){
/*Create object depending on bool*/
if(b00lvar){
Birs andor;
std::cout<<Andor.Getwidth()<<" "<<Andor.Getheight()<<std::endl;
UseObject(andor);
}else{
Citrom andor;
std::cout<<Andor.Getwidth()<<" "<<Andor.Getdepth()<<std::endl;
UseObject(andor);
}
}
Another approach would be to use two pointers, in this case passing two pointers to UseObject(). One of the two pointers will always be a nullptr, and the other one a pointer to the instantiated object, with UseObject() coded to deal with whatever object is passed in.
That's also possible, but will result in ugly code, and if I was an instructor teaching C++, I would mark down anyone who handed in code that did that.
If the type of the object (Alma or Citrom) is decided at the startup, then it's a classic polymorphism, as other answers described:
https://stackoverflow.com/a/36218884/185881
What're you missing from your design is, to name the common ancestor with common behaviors (e.g. Gyumolcs).
If the object should once act as Alma and other times as Citrom, you should implement a single class, which have a flag or enum (ACT_AS_CITROM, ACT_AS_ALMA), or, if the behavior is limited to one method, then it should have a parameter, which tells which action to perform (alma-like or citrom-like).
You can do this with pointer semantic and type introspection with dynamic_cast. I extended your example to show how I would approach it.
Here is the Demo
#include <iostream>
#include <memory>
using namespace std;
class Alma{
public:
virtual int Getwidth() = 0;
};
class Birs: public Alma{
public:
int Getwidth() { return 1; }
int Getheight() { return 2; }
};
class Citrom: public Alma{
public:
int Getwidth() { return 3; }
int Getdepth() { return 4; }
};
shared_ptr<Alma> make_attila(bool birs)
{
if (birs)
return make_shared<Birs>();
else
return make_shared<Citrom>();
}
void test_attila(shared_ptr<Alma> attila)
{
cout << "width: " << attila->Getwidth() << "\n";
if (auto as_birs = dynamic_pointer_cast<Birs>(attila))
cout << "height: " << as_birs->Getheight() << "\n";
else if (auto as_citrom = dynamic_pointer_cast<Citrom>(attila))
cout << "depth: " << as_citrom->Getdepth() << "\n";
}
int main() {
shared_ptr<Alma> attila = make_attila(true);
test_attila(attila);
attila = make_attila(false);
test_attila(attila);
return 0;
}
Next step would be to make make_attila a template function taking the Derived class as a template parameter instead of a bool.
template <class Derived>
shared_ptr<Alma> make_attila()
{
return make_shared<Derived>();
}
Two things:
If you want to use it outside the if, you will have to declare it outside the if.
You need references or pointers for this kind of polymorphism.
unique_ptr<Alma> Andor;
if (b00lvar) {
Andor = make_unique<Birs>();
} else {
Andor = make_unique<Citrom>();
}
std::cout << Andor->Getwidth() << std::endl;
Some other answer suggested using shared_ptr but that's overkill here. 99% of the time unique_ptr is sufficient.
Polymorphism isn't always the way to go if an object is known to be either a B or a C. In this case, a boost::variant is often more succinct.
Having said this, if you want to go down the polymorphic route it's important to remember something that will guide the design.
Polymorphic means runtime polymorphic. I.e. the program cannot know the real type of the object. It also cannot know the full set of possible types the object could be, since another developer could manufacture a type that your module's code knows nothing about. Furthermore, when using the Alma interface, the code should not need to know anything more. Invoking magic such as "I know it'll be a Citrom because the bool is true" is laying the foundations for a code maintenance nightmare a few weeks or months down the line. When done in commercial, production code, it results in expensive and embarrassing bug-hunts. Don't do that.
This argues that all relevant information about any object of type Alma must be available in the Alma interface.
In our case, the relevant information is whether it has the concept of height and/or depth.
In this case, we should probably include these properties in the base interface plus provide functions so that the program can query whether the property is valid before using it.
Here is something like your example written this way:
#include <iostream>
#include <memory>
#include <typeinfo>
#include <string>
#include <exception>
#include <stdexcept>
// separating out these optional properties will help me to reduce clutter in Alma
struct HeightProperty
{
bool hasHeight() const { return impl_hasHeight(); }
int getHeight() const { return impl_getHeight(); }
private:
// provide default implementations
virtual bool impl_hasHeight() const { return false; }
virtual int impl_getHeight() const { throw std::logic_error("getHeight not implemented for this object"); }
};
struct DepthProperty
{
bool hasDepth() const { return impl_hasDepth(); }
int getDepth() const { return impl_getDepth(); }
private:
virtual bool impl_hasDepth() const { return false; }
virtual int impl_getDepth() const { throw std::logic_error("getDepth not implemented for this object"); }
};
class Alma : public HeightProperty, public DepthProperty
{
public:
Alma() = default;
virtual ~Alma() = default;
// note: nonvirtual interface defers to private virtual implementation
// this is industry best practice
int getWidth() const { return impl_getWidth(); }
const std::string& type() const {
return impl_getType();
}
private:
virtual int impl_getWidth() const = 0;
virtual const std::string& impl_getType() const = 0;
};
class Birs: public Alma
{
private:
// implement the mandatory interface
int impl_getWidth() const override { return 1; }
const std::string& impl_getType() const override {
static const std::string type("Birs");
return type;
}
// implement the HeightProperty optional interface
bool impl_hasHeight() const override { return true; }
int impl_getHeight() const override { return 2; }
};
class Citrom: public Alma
{
private:
// implement the mandatory interface
int impl_getWidth() const override { return 3; }
const std::string& impl_getType() const override {
static const std::string type("Citrom");
return type;
}
// implement the DepthProperty optional interface
bool impl_hasDepth() const override { return true; }
int impl_getDepth() const override { return 4; }
};
/*...*/
/*Using them*/
// generate either a Birs or a Citrom, but return the Alma interface
std::unique_ptr<Alma> make_alma(bool borc)
{
if (borc) {
return std::make_unique<Birs>();
}
else {
return std::make_unique<Citrom>();
}
}
void Useobjects()
{
for (bool b : { true, false })
{
std::unique_ptr<Alma> pa = make_alma(b);
std::cout << "this object's typeid name is " << pa->type() << std::endl;
std::cout << "it's width is : " << pa->getWidth() << std::endl;
if(pa->hasHeight()) {
std::cout << "it's height is: " << pa->getHeight() << std::endl;
}
if(pa->hasDepth()) {
std::cout << "it's depth is: " << pa->getDepth() << std::endl;
}
}
}
int main()
{
Useobjects();
return 0;
}
expected output:
this object's typeid name is Birs
it's width is : 1
it's height is: 2
this object's typeid name is Citrom
it's width is : 3
it's depth is: 4
To avoid code duplication, I'm tring to pass pointers to functions as arguments of a static method.
I have a class (Geo) with only static methods. One of this methods (+++Geo::traceRay(+++)) should just display(Geo::display(+++)) few things, then return an int.
Another class (Las) needs to use the Geo::traceRay(+++) method, but should display(Las::display(+++)) someting else.
So I try to pass a pointer to function argument to the Geo::traceRay(+++, pointer to function) method. the pointed functon will the right "display()" method.
Up to now, passing the first pointer to display() is not an issue, but I can't find how to do it with the second one.
class Geo
{
public:
static bool display(int pix);
static int traceRay(int start, int end, bool (*func)(int) = &Geo::display); // no issue with this default parameter
};
class Las
{
public:
bool display(int pix);
void run();
};
int Geo::traceRay(int start, int end, bool (*func)(int))
{
for (int i = start; i < end ; ++i )
{
if((*func)(i)) return i;
}
return end;
}
bool Geo::display(int pix)
{
cout << pix*100 << endl;
return false;
}
bool Las::display(int pix)
{
cout << pix << endl;
if (pix == 6) return true;
return false;
}
void Las::run()
{
bool (Las::*myPointerToFunc)(int) = &display; // I can just use display as a non member class, but it should stay a member
Geo::traceRay(0,10, myPointerToFunc); // issue here!
}
int main()
{
Geo::traceRay(0,10); // use the "normal display" = the default one// OK
Las myLas;
myLas.run();
return 0;
}
You can't pass a member function pointer as a function pointer. I presume making Las::display static is not an option. In that case, I would suggest taking a std::function and using std::bind to bind the current instance:
static int traceRay(int start, int end, std::function<bool(int)> func = &Geo::display);
...
Geo::traceRay(0,10, std::bind(&Las::display, this, std::placeholders::_1));
Also, in both cases, you can call func by:
func(i);
No need to dereference it first.
What Chris suggests is great if that's as far as it goes.
Another approach to this, which would be beneficial if you have several shared functions like that, would be to use an interface (with a virtual method Display(+++)) with two implementations, put an instance of the implementation in question in each of Geo and Las (or Las could directly implement the interface). Then traceRay takes a reference to the interface base class and calls the display method on it.
I have a constant value that never changes during run-time, but is impossible to know until run-time.
Is there a way to declare a constant (either as a member of a class or not) without defining it and also assign a computed value once (and only once) it is determined; or am I going to have to resort to a non-const declaration and use coding S & Ps (ALL_CAPS variables names, static declaration if in a class, etc.) to try and keep it from changing?
CLARIFICATION:
Though these are good answers, the real-world situation I have is more complicated:
The program has a main loop that continually runs between processing and rendering; the user can set required options and once they are set they will never change until the program is restart. An "Initialize" function is set up for anything that can be determined before the main loop, but values that are dependent on user interaction must be performed in the middle of the loop during the processing phase. (At the moment, persistent data storage techniques come to mind...)
Something like this?
const int x = calcConstant();
If it's a class member, then use the constructor initialisation list, as in Yuushi's answer.
You can define it in a struct or class and utilize an initialisation list:
#include <iostream>
struct has_const_member
{
const int x;
has_const_member(int x_)
: x(x_)
{ }
};
int main()
{
int foo = 0;
std::cin >> foo;
has_const_member h(foo);
std::cout << h.x << "\n";
return 0;
}
As a static or function-local variable:
const int x = calcConstant();
As a class member:
struct ConstContainer {
ConstContainer(int x) : x(x) {}
const int x;
};
Yes, you can make a private static singleton field with an initialization method and a gettor method. Here's an example of how to do it:
// In foo.h
class Foo
{
public:
// Caller must ensure that initializeGlobalValue
// was already called.
static int getGlobalValue() {
if (!initialized) {
... handle the error ...
}
return global_value;
}
static void initializeGlobalValue(...)
private:
static bool initialized;
static int global_value;
};
// In foo.cpp
bool Foo::initialized = false;
int Foo::global_value;
void Foo::initializeGlobalValue(...) {
if (initialized) {
...handle the error...
}
global_value = ...;
initialized = true;
}