I would like to obtain an class instance from another class.
I have the following classes, with class A having B object as a private member.
class A
{
private:
B my_B;
public:
B getBInstance (void)
{
return this->my_B;
}
}
class B
{
private:
int my_attr;
public:
B ()
{
this -> my_attr = 0; //Initial value for my_attr
}
void setMyAttr (int attr)
{
this->my_attr = attr;
}
int getMyAttr (void)
{
return this->my_attr;
}
}
I want my_B to be exclusive to an object that is instantiated from class A.
When I perform the following, I am not able to change the contents of my_attr, because it accesses a different B instance everytime I call A::getBInstance().
A new_A;
new_A.getBInstance().setMyAttr(50);
printf ("%d\n", new_A.getBInstance().getMyAttr()); //Prints 0
But, if I do the following, then I get the correct output:
A new_A;
new_B = new_A.getBInstance();
new_B.setMyAttr (50);
printf ("%d\n", newB.getMyAttr()); //Prints 50
I apologize if the answer is so obvious. I suspect efforts regarding making things static or singleton pattern might help, yet I need some guidance, as I'm pretty new to this kind of implementations.
Thanks in advance,
You're returning a copy of my_B. If you want to change the one stored in A, return a reference:
B &getBInstance (void)
{
return this->my_B;
}
Related
class A {
protected:
int a;
public:
int getA() const
{
return a;
}
};
class B : public A
{
private:
int b;
public:
int getB() const
{
return b;
}
};
class C
{
private:
int c;
A* obj;
public:
C()
{
obj = new A[5];// obj is initialized with some values in the constructor, but i won't do it here
}
void f()
{
c += obj[0].getB();
}
~C()
{
delete obj;
}
};
The problem I am facing right now is that i want the f function to add to the variable c the value of b from the object obj[0] if the type of obj[0] is B. But if the obj[0] is A and not B I dont want anything to happen.
Is there a bool that would be 1 if a certain variable is a certain type?
I know i could overload the f function and make it take a parameter the B obj[0] and another one that takes as a paramter the A obj[0], the last function having an empty body, but i was wondering if there is a more simple/efficient way of doing it.
I have bee asked to provide an example of where I would need this specific solution so here it is
class Item
{
protected:
std::string Name;
unsigned long long Number;
bool Placeable;
};
class Tool : public Item
{
private:
long double AttackDamage;
long double AttackSpeed;
public:
long double getAttackDamage() const
{
return this->AttackDamage;
}
long double getAttackSpeed() const
{
return this->AttackSpeed;
}
};
class Mob
{
protected:
Item* Inventory;
unsigned long long InventorySize;
unsigned long long MainHand;
std::string Name;
long double AttackDamage;
long double AttackSpeed;
public:
Mob(unsigned long long n)
{
this->AttackDamage = 1;
this->AttackSpeed = 0.5;
this->InventorySize = n;
this->Inventory = new Item[this->InventorySize];
for (int i = 0; i < this->InventorySize; ++i)
this->Inventory[i] = e; // e in empty slot, like a 0 initializer for integers
this->MainHand = 0;
}
void setStats()
{
this->AttackDamage += this->Inventory[this->MainHand].getAttackDamage();
this->AttackSpeed += this->Inventory[this->MainHand].getAttackSpeed();
}
~Mob()
{
delete Invenory;
}
};
The method i need help with is void SetStats() in Mob. I want the function to only update the values of AttackDamage and AttackSpeed if the item at MainHand position is a Tool. Otherwise i dont want any updates. I could add stas to the Item class like AttackDamage and AttackSpeed and set them to 0 which would make no issue but if i would be working on a more serious project i would have more stats than AttackDamage and Speed and there would be a lot of unnecesarry memory.
This is just a fraction of the code, like not all variables are initialized and there might be some things i forgot to paste
You need at least one virtual function in the base class, otherwise there is no polymorphism. The canonical way is to define a virtual destructor:
class A {
// ...
virtual ~A() = default;
};
To use polymorphism, you can't have value types. You need pointers or references. So instead of A obj, you'd need to use A* obj. You then try to dynamic_cast obj to a B* pointer. If obj is indeed pointing to a B, the cast succeeds and returns a valid B* pointer you can use. If obj is not pointing to a B, the cast fails and returns a null pointer:
class C {
private:
int c;
A* obj;
public:
void func()
{
if (auto casted_obj = dynamic_cast<B*>(obj)) {
c += casted_obj->getB();
}
}
};
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 code like this:
class Human
{
protected:
int age;
std::string sex;
public:
virtual void speak() = 0;
};
class Child:public Human
{
public:
void speak(){std::cout << "I am Child\n";}
};
class Man:public Human
{
public:
void speak(){std::cout << "I am Man\n";}
};
class Woman:public Human
{
public:
void speak(){std::cout << "I am Woman\n";}
};
(don't know, std::shared_ptr<Human> maybe?) operator*(std::shared_ptr<Child> &b, int x)
{
b->setAge(b->getAge()+x);
if(b->getAge()>18 && b->getSex()=="Man")
{
return (i want b to become std::shared_ptr<Man>)
}
if(b->getAge()>18 && b->getSex()=="Woman")
{
return (here I want b to become std::shared_ptr<Woman>);
}
return;
}
int main(){
auto x = std::make_shared<Child>;
x*19;
}
I know it seems odd, but it's the simplest case i can think of, without having to write down all code i'm struggling with rn. Could someone explain, what type should overload be and how to change shared_ptr type, knowing they derive from same parent?
Objects cannot change type. A Child object will always be a Child object. What you can do is create a new object with the properties you want and return that:
std::shared_ptr<Human> operator*(std::shared_ptr<Human> b, int x)
{
b->setAge(b->getAge()+x);
if(b->getAge()>18 && b->getSex()=="Man") {
return std::make_shared<Man>(b->getAge());
} else if(b->getAge()>18 && b->getSex()=="Woman") {
return std::make_shared<Woman>(b->getAge());
} else {
return b;
}
}
int main(){
std::shared_ptr<Human> x = std::make_shared<Child>;
x = x*19;
}
This doesn't seem like a good design though. A Human's status as a child or adult would be better represented as an attribute of the object or by a function that checks if age is greater than 18.
You cannot make the type T<Derived> inherit from T<Base> because C++ templates do not support covariance. To do so would be unsafe for certain types, such as mutable references to containers. (Imagine taking a reference to std::vector<Cat> as std::vector<Animal>& and pushing back a dog!)
(I would make this answer a comment, but I don't have comment abilities.)
Update:
You can write a non-template wrapper that handles heap data:
class Wrapper
{
public:
Wrapper(Base* b) : raw(b) {}
~Wrapper() { delete raw; }
Base& get() { return *base; }
private:
Base* raw;
}
Of course, in your example, you use std::shared_ptr and not std::unique_ptr. You would have to handle reference counting instead of simply deleting the data in the destructor, but the technique of keeping an internal raw pointer still stands.
Update 2:
The above code could be used as is to provide a level of indirection, such that all classes that inherit from the base class may be held in the same type, without writing your own reference counter:
std::shared_ptr<Wrapper>
This solution may be seen as similar to doing std::shared_ptr<Base*>, except that the latter solution would leak memory.
I'm trying to modify some variables [not necessary from the same class/struct] from keyboard's shortcuts, something like that:
A foo struct containing variables:
struct Foo {
int a;
float b;
};
struct Foo2 {
int c;
};
And a main like:
int main() {
Foo f;
Foo2 f2
void* p = &(f.a); //it could be &(f2.c)
if ('A' key activated) {
*p += 1;
}
}
Currently, I'm stucked at this point:
error: invalid operands to binary expression ('void' and 'int')
The only way to make it work is to change:
*p += 1;
By:
*(int*)p += 1;
Which is not a good solution, because I should not know the type pointed by p. Is there a way to do that?
Converting the pointer to void* lost the type information and the compiler will not know how to increment. Why don't you make a pointer to Foo instead?
int main() {
Foo f;
Foo* p = &f;
if ('A' key activated) {
p->a += 1;
}
}
Also keep in mind that incrementing a float is not a good idea!
For the quesion in the comment of this answer:
struct FooBar
{
int *a;
float *b;
};
int main() {
Foo f;
Bar b;
FooBar fb{&f.a, &b.b};
if ('A' key activated) {
*(fb.a) += 1;
}
}
Note that this solution is rather C-style. Look at lethal-guitar's answer for a more C++-style solution.
Edit: At first I didn't realize that you want to have different types per entry. Based on the task of handling keyboard shortcuts, you could use a polymorphic class, and put instances of it into a std::map:
class KeyHandler {
public:
virtual void onKeyStroke() = 0;
};
class MyHandler : public KeyHandler {
public:
MyHandler(int& value) : myValue(value) {}
virtual void onKeyStroke() {
myValue_ += 1;
}
private:
int& myValue_; // Other subclasses could have other data
};
// Now place instances of different Handlers into a std::map
typedef std::shared_ptr<KeyHandler> PKeyHandler;
std::map<char, PKeyHandler> bindings;
bindings['A'] = PKeyHandler(new IncrementIntHandler(&someInt));
bindings['B'] = PKeyHandler(new IncrementFloatHandler(&someFloat));
// The actual input handler then just invokes
// the correct handler for a key stroke.
bindings[keyCode]->onKeyStroke();
That way, you can define a handler class for every action you want to support, and implement the corresponding logic into these classes. You could make the base class' implementation just do nothing to handle non-mapped keys, etc.
Sure, use an int pointer instead:
int * p = &f.a;
if ( /* condition */ ) { ++*p; }
I am confused on how to fill a vector with values from a different class.
Can anyone give me a coded example how this is done. :)
Class A
{
//vector is here
}
Class B
{
//add values to the vector here
}
main()
{
//access the vector here, and print out the values
}
I appreciate the help <3
It seems like a quick lesson in access levels and encapsulation is in order.
My guess, based on the questions touch is that you're looking for the following code.
int main()
{
ClassA[] as = {new ClassA(), new ClassA(), ... }
ClassB[] bs = {new ClassB(), new ClassB(), ... }
}
But I'm shooting in the dark, a bit. :)
You should make your question more specific, edit it and post what you've tried to do. If you mean to do something respecting oop-rules, the play looks like this:
#include<iostream>
#include<vector>
class A{
public:
void fill_up_the_vector() { v=std::vector<int>(3); v[0]=0; v[1]=1; v[2]=4; }
void add( a.add(i); ) { v.push_back(i); }
void display_last() const { std::cout<<v[v.size()-1]; }
private:
std::vector<int> v;
};
class B{
public:
B(){ a.fill_up_the_vector(); } // B just *instructs* A to fill up its vector.
void add_value(int i) { a.add(i); }
void display() const { a.display_last(); }
private:
A a;
};
int main()
{
B b;
b.add_value(9);
b.display(); // reads v through A.
}
Note that this example above is a bit different from what you've asked. I posted it since I think you sould keep in mind that according to OOP rules
you don't want to access values in A directly,
B should have a member with type A if you plan to access a value in A,
you're supposed to access a value in A through B if you have filled it up from B.
The other way to go is not OOP:
struct A{
std::vector<int> v;
};
struct B{
static void fill_A(A& a) const { a.v = std::vector<int>(3); a.v[0]=0; a.v[1]=1; a.v[2]=4; }
};
int main()
{
A a;
B::fill_A(a);
a.v.push_back(9);
std::cout << a.v[a.v.size()-1];
}
but this code is as horrible as it gets.