I'm trying to set the value of a member of a class from another class using this snippet. Here is a sample of the code I'm trying to make work
class A
{
private:
int a;
public:
A()
{
a = 0;
}
A(int val)
{
a = val;
}
int GetA()
{
return a;
}
void SetA()
{
a = 290;
}
};
class B
{
B(){};
void SetB()
{
A a;
a.SetA();
}
};
int main(){
A a;
B b;
b.SetB();
cout << b.GetA();
}
How can I make this code pint out 290.I currently prints out 0
In SetB your A variable is a temporary that is destroyed when the function returns.
The way it is written in your snippet, your code won't compile, because B has no method GetA(). From your use case (the code in main()), I suspect you either want B to inherit from A:
class B : public A
{
public:
B() {];
void SetB()
{
SetA();
}
};
although that doesn't make too much sense, because in this case you could just call b.SetA() directly. Or, you want an object of type A as a member of B:
class B
{
public:
void SetB()
{
a.SetA();
}
int GetA()
{
return a.GetA();
}
private:
A a;
};
But it's a bit hard to tell from your snippet what you're actually trying to achieve.
Also, you probably want your Get…() methods to be const.
If you;re trying to achieve what I think you're trying to achieve then you're nearly there, it is just that you are creating two versions of A, one on the main stack, and one that is a temporary inside B::SetA()
try passing A as a reference parameter to B, so that there is only one version of A.
void SetB(A& a)
{
a.SetA();
}
then your calling code would be:
A a;
B b;
b.SetB(a);
cout << a.GetA();
Alternatively, pass a in the constructor of B and store A as a reference member in B;
Related
The goal of the code structure below is to be able to store pointers to objects of any class inherited from 'A'.
When I run this code, I get 0 written out, but what I'm trying to access is the 'B' object's 'num' value, which is 1. How can I do that?
As far as I know, when you create an inherited class's object, you create an object of the parent class too automatically. So can I somehow access the parent class object from it's child and set it's class member to match?
See minimal reproducible example below.
Update: Virtual functions solved the problem.
#include <iostream>
class A
{
public:
int num;
A()
{
num = 0;
}
};
class B : public A
{
public:
int num;
B()
{
num = 1;
}
};
class C
{
public:
A* ptr_array[2];
C()
{
ptr_array[0] = new B();
}
void print()
{
std::cout << ptr_array[0]->num << std::endl;
}
};
int main()
{
C* object_c = new C();
object_c->print();
return 0;
}
The problem is that you define a member num in A, and another member num in B. So an object of type B has two members called num, and you're leaving it to the compiler to choose which one to use -- which it does, according to logical rules which may be unfamiliar to you.
If you remove the line in num; from the definition of B, the code will work as you intend.
Your array is a red herring. You are only using one pointer. Might just as well have it as a member for the sake of the example.
I suppose you might need something like this (note, untested code).
#include <memory>
#include <iostream>
class A {
public:
A() : m_num(0) {} // use this instead of assignment in the c'tor body
virtual int getNum() { return m_num; } // this is **the** way to use inheritance
virtual ~A() = default; // required
private:
int m_num;
};
class B : public A {
public:
B() : m_otherNum(1) {}
virtual int getNum() { return m_otherNum; } // does something different from A
private:
int m_otherNum; // you could also call it m_num, but for clarity I use a different name
};
class C {
public:
C() : m_a (std::make_unique<B>()) {} // note, use this instead of new B
void print() {
std::cout << m_a->getNum() << std::endl;
}
private:
std::unique_ptr<A> m_a; // note, use this instead of A* m_a;
};
I have no way of knowing if this is really what you need (or you think you need). This is how inheritance is supposed to be used in object-oriented programming. You can use it in various other ways and produce correct (as far as the language definition is concerned) programs. But if this is the case, then (public) inheritance is likely not the best tool for the job.
I would like to ask the following:
Suppose that we have three classes in C++: A, B and C. An object of class A is creating and owning an object of class B. It is then giving the reference of B to an object of class C to be stored as a pointer variable. So, what is the best practice to inform C, that the pointer to B is no longer valid (and should be set to null), if A is deleted?
Is there a general approach or for example a Qt specific one?
Use std::weak_ptr
Example (live demo here)
class A
{
private:
std::shared_ptr<B> myB;
public:
A() :
myB(std::make_shared<B>())
{
}
std::weak_ptr<B> GetB()
{
return myB;
}
};
class B
{
};
class C
{
private:
std::weak_ptr<B> theB;
public:
C(std::weak_ptr<B> b) :
theB(b)
{
}
void test()
{
auto b = theB.lock();
if (b)
{
// theB is still valid
}
else
{
// theB is gone
}
}
};
class A
{
class B
{
int x;
}
public:
void printX() { std::cout << ????; }
}
How can I access the x variable from the A class function? I can't make it static either...
I tried everything but it either tells me I need an object in order to access it or the compiler doesn't find the function.
it either tells me I need an object [...]
Think about that. Because that's exactly what the problem is here.
If you instantiate an A, you don't also get a B. A nested class isn't a member variable of the enclosing class. It's really just another way to change the namespace of a class.
So, you need an instance of B. Perhaps a member of A?
class A
{
class B
{
public:
int x;
} mB;
public:
void printX() { std::cout << mB.x; }
};
You don't ever declare an instance of the class B inside A. You need to do something like this:
class A
{
class B
{
public:
int x;
};
B b;
public:
void printX() { std::cout << b.x; }
};
You don't. You do need an object in order to use the x variable. You could, however make it static. The problem with your example is x is not public. Placing B inside A does not make B part of A, it only changes B's scope.
From this example it kinda looks like you're after inheritance instead. This would give you the effect you're after ( access to all B's methods and variables without making an object. )
Class B
{
protected:
int x;
}
Class A : B
{
void printX() { std::cout << x; }
}
I have two classes with one extending the other. They both have a method called doSomething() that perform something different. I want to be able to have one pointer that I can switch from class A to class B and have the rest of the code run the same because they each have the same method name. Is this possible and is this the correct way to do it? Also, I'm pretty new to C++ so it could be just a problem with that.
class A {
void doSomething()
{
// does something
}
};
class B: public A {
void doSomething()
{
//does something else
}
};
main()
{
A *ptr = new A;
B *bptr = new B;
// a giant loop
ptr->doSomething();
if(condition)
{
ptr = bptr;
}
}
Two ways I can think of to accomplish this.
Your way is fine (with some small changes) if you already have polymorphic types). (If B is-an A, logically)
class A
{
public:
virtual void f() { /* something */ };
};
class B : public A
{
public:
virtual void f() { /* something else */ };
};
int main()
{
A a;
B b;
A* c = 0;
// based on your condition
c = &a;
c->f();
c = &b;
c->f();
return 0;
}
But what if your types aren't really that closely related? Using inheritance implies a very rigid (is-a, in this case) relationship between your classes. Is a B really an A?
Here's a way to accomplish this for classes that have the same named function, but aren't really of similar types.
template <class T>
void do_f(T& obj)
{
obj.f();
}
class D
{
public:
void f() { /* something */ }
};
class E
{
public:
void f() { /* something else entirely */ }
};
int main()
{
// note, D and E have no relation
D d;
E e;
// based on your condition
do_f(d);
do_f(e);
}
What you are trying to achieve is called polymorphism. In C++, you will need to define a common (possibly abstract) base class C for A and B, make doSomething a virtual function, override it in both A and B, and make pointers of type C*. Here is a good introductory article on the topic.
to create an instance of another class from a class even if the class I want to have an instance of is declared next of the class I am creating an instance from. Just like in C# and Java.
Thank you
You can use a forward declaration for some purposes, but you will need to have the complete type whenever you actually make use of it. It could be advisable to make the question more specific as to what you really want to achieve, as there might be simpler approaches to your problem (if order is important it might indicate a circular dependency between classes A and B, and that is not usually good).
class B;
class A
{
public:
A( B b, B* bp, B& br ) : bp_(bp), br_(br) {} // ok, incomplete types can be used as argument types
B f()
// { return B(); } // nok: cannot create objects of incomplete type
;
B* f2() { return bp_; } // ok
B& f3() { return br_; }; // ok
void g()
// { bp_->g(); br_.g(); } // nok: cannot call methods of an incomplete type
;
void g( B const & b )
// { b.g(); } // nok: cannot call methods of an incomplete type
private:
B * bp_; // ok (also const version)
B & br_; // ok (also const version)
// B b_; // nok: B must be a complete type here
};
class B { // A is complete, any use is correct here
void g() {}
};
// From here on, B is a complete type and can be used in any possible way
B A::f() {
return B(); // ok, now B is complete
}
void A::g() {
br_.g(); // ok, B is complete here
bp_->g(); // ok, B is complete here
}
void A::g( B const & b ) {
b.g();
}
Sure. You just need a forward declaration. Something like this works just fine:
#include <iostream>
class B;
class A {
public:
void hello( B &b );
void meow();
};
class B {
public:
void hello( A &a );
void woof();
};
void A::hello( B &b ) { b.woof(); }
void A::meow() { std::cout << "Meow!" << std::endl; }
void B::hello( A &a ) { a.meow(); }
void B::woof() { std::cout << "Woof!" << std::endl; }
int main() { A a; B b; a.hello( b ); b.hello( a ); return 0; }
The key here is that you can only use pointers or references to a class until it has been fully defined. So in the example I gave, the hello() method in A can be declared to take a reference to B, even though we haven't defined B at the point. After the definition of B, however, the definition of the method A::hello() is free to use B as it pleases.
I guess you mean to do something like this:
class B; //Forward declaration
class A
{
private:
B b;
};
class B
{
};
This is not possible in C++ as the compiler needs to know the sizeof(B) when compiling class A.
As a solution what you can do is:
class B; //Forward declaration
class A
{
public:
A();
~A();
private:
B* m_pB; //Store a pointer to B
};
class B
{
};
A::A()
{
m_pB = new B; //Create an instance of B
}
A::~A()
{
delete m_pB; //Explictly deallocate the memory.
m_pB = NULL;
}
Once you forward declare B in the header you can use it in the .cpp file without trouble to access public variables and methods.