I have two classes. In the class A constructor, I am calling the constructor of class B. However, while creating class B object, I want to pass the QSCOPED pointer of the class A object. In short, instead of this pointer, I want to pass the QSCOPED pointer. How can I do so?
class B;
class A
{
class A();
};
A::A()
{
QScopedPointer<B> m_p_B( new B(this));
}
My requirement is that instead of passing this pointer, I want to pass the QSCOPED pointer of the class A. Basically a QSCOPED pointer of this pointer. How can I do so?
Something like this:
It's not needed to pass QScopedPointer in the constructor, it will be created in the initializer list.
#include<QScopedPointer>
class B
{
public:
B(A* a) : ma(a) {}
private:
QScopedPointer<A> ma;
}
Related
The following is some architecture I have designed.
I have a class X that has a variable member Y that is a pointer (or reference, I haven't decided yet) to class A. Class A is an abstract class. The user of X can create his own derived class from A (for example B:A) and pass it to X (probably, in the constructor) which, somehow, will store it in Y.
To make this work, the user should dynamically allocate an object of type B:A and pass it to X. However, can you think of a simpler way, for the user, of doing this without having to call new? Ideally, I would like the user to simply create an object of type B:A and pass it. Then, the constructor of X, somehow, would define Y using it (maybe creating a copy of B:A). The problem is that X doesn't know which derived type is passed and what size it is.
I want to create a single constructor to which the user could pass any type derived from A as parameter, and would be converted into a member variable. It should allow the user to create his own type for taking advantage of polymorphism.
class A {...}; // Abstract class (has pure virtual members)
class B : public A {...}; // Class defined by the user
class X
{
public:
X(A ¶m) { /* abc is defined */ }
A* abc;
}
Some ideas I had:
Could it work a pure virtual copy assignment operator overloading at A? And having a member at B:A that specifies the size of B:A? However I still don't know how to make it work.
How to solve it? Is there maybe a better way? Thanks in advance.
To make this work, the user should dynamically allocate an object of type B:A and pass it to X. However, can you think of a simpler way, for the user, of doing this without having to call new?
Polymorphism is not dependent on new being used. It simply requires a pointer/reference to the polymorphic object. The caller could create its derived object statically, if it wants to. Just so long as the object outlives the X object that refers to it.
Then, the constructor of X, somehow, would define Y using it
That is not possible. The Y member would have to be statically typed at compile-time, ie as an A* pointer or A& reference. Unless X is written as a template class, so that the user can then specify the actual derived type being passed in.
maybe creating a copy of B:A
That is possible, but only if X is templated, otherwise A will have to declare a virtual clone() method that all derived classes override to make copy of themselves.
The problem is that X doesn't know which derived type is passed and what size it is.
Polymorphism doesn't need to know that info.
You could simply require the class to implement the copy operation (the Clone function below):
class A
{
public:
virtual ~A() = default;
virtual std::unique_ptr<A> Clone() const = 0;
};
class B : public A
{
public:
std::unique_ptr<A> Clone() const override
{
return std::make_unique<B>(*this);
}
};
class X
{
public:
X(A const& param)
: abc(param.Clone())
{
}
// allow transferring an object stored in a unique_ptr to the object
template<class T> requires (std::is_base_of_v<A, T>)
X(std::unique_ptr<T>&& param)
: abc(std::move(param))
{}
private:
std::unique_ptr<A> abc;
};
Note that if you restrict the user to transferring the ownership to of the subclass of A to X, you don't need to Clone functionality at all. You you could remove X::X(A const&) and Clone in this case. The user would still be able to create your object like this:
X x = std::make_unique<B>();
X x(std::make_unique<B>()); // alternative syntax for the above
On the assumption that class X is going to own param after it is passed in, you can do this:
#include <iostream>
#include <memory>
class A { public: virtual ~A () {} };
class B : public A { public: ~B () { std::cout << "B destroyed"; } };
class X
{
public:
X (std::unique_ptr <A> ¶m) : m_param (std::move (param)) { }
private:
std::unique_ptr <A> m_param;
};
int main ()
{
std::unique_ptr <A> b = std::make_unique <B> ();
X x (b);
}
When run, this code prints B destroyed. Note that, for this to work, A must have a virtual destructor.
If ownership of param is to be shared with the caller and / or other objects, use std::shared_ptr instead (but this has more overhead). Or, as #Remy says, if you can guarantee that the lifetime of param exceeds that of x, you can store a raw pointer (or reference).
Edit: As per the comments, a better implementation of the constructor of class X would be:
X (std::unique_ptr <A> &¶m) : m_param (std::move (param)) { }
And then you would call it like this:
X x { std::make_unique <B> (); }
This makes it clear that x owns the object passed in.
So I have class A, which has an object of class B as a class variable.
I constructed an object of class B in the main (objB) , and use class A's constructor to pass objB into class A (and assigned it to class variable called objC of type B).
How can I make it so whenever I call objC.do() it can change the original objB as well?
Instead of having a B member, use a reference as a member:
class A {
B& the_b;
// etc.
public:
A(B& some_b) : the_B { some_B } { }
}
Is it safe to remove the only shared_ptr reference to itself inside a method? Something like the following. If two objects, one of class A and the other of class B, points to each other via their pB_ and pA_. Suppose pB_ is the only reference to the object of class B. Then I call A::method() on the object of class A. Will there be any problem?
#include <iostream>
using std::shared_ptr
class B;
class A {
public:
void method() {
pB_->method();
}
shared_ptr<B> pB_;
};
class B {
public:
void method() {
pA_->pB_.reset();
// Is this OK? And is it safe if I don't do this?
some_other_data_ = 10;
}
shared_ptr<A> pA_;
int some_other_data_;
};
Resetting that pointer will result in the B object being deleted, so no, it is not okay to access one of its members after that point. For more info, see: Is it safe to `delete this`?
Consider this code:
struct A {};
struct B
{
B(A* a) : a(a) {}
private:
A* a;
};
struct base
{
base(B b) : b(b) {}
protected:
A a;
private:
B b;
};
struct derived : public base
{
derived() : base(B(&a)) // <-- IS THIS OK?
{}
};
Here, the base class needs a B object passed to its constructor by the derived class, and the B object refers to an A object, but the A object lives inside the base class.
The constructor of the B object does not do anything to the A pointer except store it, so I'm thinking this should be OK, but it still feels wrong because technically the A object doesn't yet exist at the time I'm passing it to the base constructor.
Can I get into trouble doing this or should this be OK?
It is safe as long as you don't use a in B's constructor, as the object a isn't constructed yet.
I mean, you shouldn't dereference the pointer a in B's constructor; however after base's constructor is executed, you can safely dereference B::a in other methods of B.
a has not been constructed, but it does have an address, and it is legal to take its address at this point. You do need to be sure, though, not to use the pointer in the constructor of B (i.e., don't dereference the pointer).
This is all rather awkward, though.
Okay, consider the following classes:
class Object
{
public:
// Constructor
Object() :
[Initialization List]
{
...
}
...
};
class Container
{
public:
Object A;
Object B;
....
Container() :
[Initialization List]
{
}
};
I'd like to provide [access to Container and it's members] to the Objects.
My first thought was to somehow pass a reference to the current Container object to the constructors of the Objects. But I can't figure out how to do this.
I've messed around with "this", but I'm not getting anything that works. I tried something like this:
class Object
{
public:
Container& c
// Constructor
Object(Container& c_) :
c(c_)
{
...
}
...
};
class Container
{
public:
Object A;
Object B;
....
Container() :
A(Object(this))
B(Object(this))
{
}
};
My eventual goal is to be able to access Object B from inside a member method of Object A.
Does anyone have any insight on how to get closer to what I'm looking for?
Thanks!
It is not UB or bad, necessarily, to use this in an initializer list, although care is needed, and your code is perfectly valid with minor modification.
class Container;
class Object
{
public:
Container& c
// Constructor
Object(Container& c_) :
c(c_)
{
}
};
class Container
{
public:
Object A;
Object B;
Container() :
A(Object(*this))
B(Object(*this))
{
}
};
this is a pointer, you wanted a reference, and a simple de-reference will do the trick. This is perfectly legal and defined code. What's not allowed is to access any member data or functions through the pointer, because those member data or functions simply may not exist yet until the init list is finished. But it definitely is allowed to take a pointer or reference to an object during it's initializer list and pass it around.
How about just using pointers? Edit: fixed code to avoid this in initializer list.
class Container;
class Object
{
public:
Container *c;
// Constructor
Object(Container *c_) :
c(c_)
{
}
};
class Container
{
public:
Object *A, *B;
Container()
{
A = new Object(this);
B = new Object(this);
}
};
You shouldn't pass this in initializers for members of the class whose instance you're constructing, but you can pass it later, so there's two easy ways around your problem
use a setter on the object (A.setContainer(*this)) in the constructor's body
make A and B pointers, initialize them to NULL and do a A = new Object(this) in the constructor's body