In C++, I want to initialize (or change) a class object using the result of another class' method. Can I use the this pointer? Is there a better way?
Dummy example:
class c_A {
public:
int a, b;
void import(void);
};
class c_B {
public:
c_A create(void);
};
void c_A::import(void) {
c_B B;
*this = B.create();
};
c_A c_B::create(void) {
c_A A;
A.a = A.b = 0;
return A;
};
There is no problem. The member function void import(void); is not a constant function.In this statement
*this = B.create();
there is used the default copy assignment operator.
Is there a better way?
A better way is not to use a member function and just use an assignment statement for objects of the class as for example
c_A c1 = { 10, 20 };
c1 = c_B().create();
Related
I have class A, is it possible to make sth like this? A(A(A()))? I mean creating some object in constructor and so on?
class A {
private:
A *a;
public:
A(){
printf("A()\n");
}
A( A * var){
printf("A(A)\n");
a = var;
}
};
int main() {
A x = A(A(A()));
return 0;
};
and this give me output A(), i mean why not A() A(A) A(A)? My A class represent a memory cell so A(1) is pointing to array[1] but A(A(1)) is sth like array[array[1]]. But i don't have idea how to implement this, only one object is created. (this A class is just an example of what I want to achieve)
I have a Derived class whose constructor has to populate the fields of a struct that is passed as an argument to the constructor of the Base class. I want to be able to name the fields of the struct that I am populating, to keep my code future-proof (i.e.: resistant to addition and/or reordering of the members of MyStruct).
Note that struct MyStruct has default values, so it cannot be initialised with named fields directly in the initialization list (e.g.: Base({.a = a, .b = b}) does not work). Also, in my case, Base's copy constructor is deleted. Also, I am using C++ 11.
The solution I came up with uses the placement new operator to manually call the constructor of the Base class on the memory pointed to by this. To achieve this I also had to add a protected default constructor to my Base class. Are there any possible downsides to this approach and/or could anyone suggest a better method?
#include <iostream>
struct MyStruct
{
int a = 0;
int b = 1;
};
class Base
{
public:
Base(MyStruct str){
std::cout << "a: " << str.a << ", b: " << str.b << "\n";
}
Base(Base&&) = delete; // no copy constructor
protected:
Base(){ // dummy, does exactly nothing.
// it only exists to be called by
// the derived class's constructor
}
private:
int amember;
};
class Derived : public Base
{
public:
Derived(int a, int b)
{
MyStruct str;
str.a = a;
str.b = b;
new (this) Base(str);
}
private:
int anothermember;
};
int main()
{
MyStruct str;
str.a = 10;
str.b = 20;
Base b(str);
Derived d(10, 20);
return 0;
}
edit: added mention that Base cannot be copied, made explicit that Base::Base() does exactly nothing.
Use a helper function instead like
class Derived : public Base
{
public:
Derived(int a, int b) : Base(make_mystruct(a, b)), anothermember(some_value) {}
private:
int anothermember;
static MyStruct make_mystruct(int a, int b) { return MyStruct(a, b); }
};
I would just like to add that this could be a good opportunity to use IILE, Immediately Invoked Lambda Expression, if you for whatever reason don't want a named helper function:
class Derived : public Base
{
public:
Derived(int a, int b) : Base{[](){
MyStruct str;
str.a = a;
str.b = b;
return str; }()}
{}
};
The benefit is that you will not need to construct the class and it's members only once, since you do everything in the initialization list. If you in the future add non-trivial members to Base, you will be will not have to pay for double initialization.
I have a class A that provides methods to construct instances of class B. And B holds a private reference to A and provides a constructor to set this reference.
class A {
public:
B* construct_B ();
}
class B {
private:
const A& private_A;
public:
B ( const A& my_A ): private_A (my_A) { }
}
The implementation of construct_B takes care of dynamic allocation and passing the reference to itself via this.
How do I implement this setup in such a way that I make sure that the lifetime of A is longer than B so that its reference remains valid? Notice that I don't care about all the possibilities of construct_B instead of returning a raw pointer I could return a smart pointer or similar.
One possible way of solving this could be having B instead of holding a reference to hold a smart pointer to A, and instead of dynamically allocating B in construct_B to take a static reference to B and then set it's pointer, something like
class A :
public std::enable_shared_from_this<A> {
public:
void setup_B ( const B& my_B ) {
my_B.set_A (shared_ptr_from_this() ) ;
}
class B {
private:
const shared_ptr<A> private_A_ptr;
public:
void set_A ( const shared_ptr<A> my_A ):
private_A_ptr (my_A) { }
}
which then could be implemented by
int main () {
A static_A;
B static_B;
A.setup_B (static_B);
}
Does the shared_ptr of this last construction avoid the problem of A being deleted before B?
shared_ptr is your answer. Something like this:
#include <memory>
struct A;
class B {
const std::shared_ptr<A> private_A_ptr;
public:
B(std::shared_ptr<A> parent) : private_A_ptr(std::move(parent)) {}
};
struct A :
std::enable_shared_from_this<A>
{
B make_b() {
return B(shared_from_this());
}
};
int main()
{
// this would be invalid:
//A a;
//auto b = a.make_b();
// but this is fine
auto pa = std::make_shared<A>();
auto b = pa->make_b();
// later...
pa.reset();
// A still exists because ownership was shared with b
}
I need to delay the constructor call, so I can initialize the value that should be passed to the constructor. I have written a short and very simplified example.
class A
{
private:
ObjectA* _ptr;
public:
A(ObjectA*);
};
class B
{
private:
A object; // The constructor seems to be called here?
ObjectA* obj;
public:
B();
};
A::A(ObjectA* ptr)
{
this->_ptr = ptr;
}
B::B()
{
obj = new ObjectA();
object(obj); // I want to call the 'A' constructor here, after initializing of 'obj'.
}
Is it possible?
No, you cannot defer a construction of a value member. You can use a pointer instead of a direct value but that's no solution for your problem.
The proper solution for your problem is using initialization list:
B::B ( ) : obj(new ObjectA), object(obj) {}
Also, you have to put obj before object in class B:
class B
{
private:
ObjectA *obj;
A object;
public:
B ( );
}
The reason for this is that, when a constructor is called, all of the objects members must be properly constructed and initialized. This is done using their default constructor.
The reason for reordering the class members is that the initializers of the members are called in the order they are declared in the class not in the order of their appearence in the initialization list.
Here is a solution I would use.
class B
{
private:
char m_aBytes[sizeof(A)];
A& getA () { return *(A*)m_aBytes; }
public:
B ()
{
ObjectA* objA = new ObjectA ();
new (m_aBytes) (objA);
}
}
I've always worked with pointers and avoided references because I didn't understand how to work with them very well. Today I was working on a small project and decided to use references instead and ran into some behavior I'm not sure how to work around. Basically I have a factory (Factory) that creates either an object of type B or C, both of which are derived from A.
class Factory
{
public:
void create(A& container, int a) //This is for creating an object of B
{
B result;
result.Func(a);
container = result;
}
void create(A& container, int a, int b) //This is for creating an object of C
{
C result;
result.Func(a, b);
container = result;
}
}
class A
{
public:
virtual void Func(int a) //This is used for an object of B
{
var1 = a;
};
virtual void Func(int, int) {}; // This is used for an object of C
private:
int var1;
}
class B : public A
{
//Relies of base class Func to set the variable var1;
}
class C : public A
{
public:
void Func(int a, int b)
{
A::Func(int a)
var2 = a1;
}
private:
int var2;
}
The issue arises when I try to do the following
Factory factory;
A a;
factory.create(a, 1); //Works fine because B and A have only 1 variable
factory.create(a, 1, 1); //a only contains A part of C
When I check the debugger, there is no sign of var2 to in a after the 2nd create call. I understand its because I'm using a reference to the base type of C and only the A part of C gets stored in the container, but is there a workaround? I know I can just switch A to A*, but I'm interested if there is a non-pointer based solution.
TL;DR
Is there a way to store an object of a derived class in a reference of the base class without using pointers?
I feel compelled to point out that a reference of type T is logically equivalent to a T * const. So technically, you can't get around using pointers.
To answer your question, it is absolutely possible to store a derived class in a reference to a base class. The issue is that A, B, and C all have potentially difference sizes. Here is one solution:
#include <stdio.h>
class A
{
public:
virtual void Function()
{
printf("A\n");
}
};
class B : public A
{
public:
virtual void Function()
{
printf("B: %d\n", var1);
}
int var1;
};
class C : public A
{
public:
virtual void Function()
{
printf("C: %d, %d\n", var1, var2);
}
int var1, var2;
};
class Factory
{
public:
A & Create(int a)
{
B &b = *new B;
b.var1 = a;
return b;
}
A & Create(int a, int b)
{
C &c = *new C;
c.var1 = a;
c.var2 = b;
return c;
}
};
Called like:
Factory factory;
A &a1 = factory.Create(0);
A &a2 = factory.Create(1, 2);
a1.Function();
a2.Function();
Which will print:
B: 0
C: 1, 2
Unfortunately, it's not possible to allocate an A and then assign a B or C to it later, since their sizes don't match. You either must use a reference/pointer with dynamic allocation, or know the type ahead of time.