how to pass object to constructor by ref or pointer? - c++

Something goes wrong here and I can't understand what that is.
There is my class
class EmulatorCameraMng : BaseCameraManager
{
public:
EmulatorCameraMng(EmulatorCameraConfigParser & parser) : m_parser(&parser) {};
~EmulatorCameraMng() {};
public:
void load_configuration_from(const std::string & json_config_file_name);
private:
EmulatorCameraConfigParser * m_parser;
std::vector<emulator_context::EmulatorContextObj> * m_emulator_context_objects;
};
It take a parser as a param in the constructor.
Now, I need to create this EmulatorCameraMng obj and pass this parser:
EmulatorCameraConfigParser m_parser;
camera_manager::EmulatorCameraMng m_emulator_manager(m_parser);
Actually, what I want to do is pass object to another object as a param in a constructor without calling a copy constructor. So, there are two ways, by reference or by pointer, but neither of them work.
What am I doing wrong?

Within a class definition, something of the form camera_manager::EmulatorCameraMng m_emulator_manager(m_parser); is syntactically a member function declaration. You get an error there because you name an object not a type.
You will need to pass m_parser to m_emulator_manager in each constructor's member initialiser list, e.g.
class Foo {
EmulatorCameraConfigParser m_parser;
camera_manager::EmulatorCameraMng m_emulator_manager;
public:
Foo() : m_emulator_manager(m_parser) {}
}

Related

Let the user pass a user-defined type as sub-class of the parameter class to define a member

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 &param) { /* 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> &param) : 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> &&param) : 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.

How can I initialize a member const reference in a derived class, when I wish to call a base class constructor?

I cannot find this question even being asked anywhere...so that makes me believe i'm doing something very wrong here...
Lets say I have a base class, A, with a constructor that takes in int parameter.
In my derived class, B, I wish to invoke that constructor but also initialize a member reference passed in B's constructor. How can i do this? I cannot find the syntax to add an initialization list if I call the base class constructor. Is this possible?
Lets say I have:
Class Object
{
Object(){}
}
Class A
{
A(int number) : m_number(number){}
public:
int m_number;
}
Now, how would I initialize m_obj if i wish to call the non-default constructor of A?
e.g.
Class B : Class A
{
B(int number, const Object& objRef) : A(number)
{
m_obj = objRef; //error, : must be initialized in constructor base/member
// initializer list...but I cannot access an initializer list!!
}
private:
const Object& m_obj;
}
as I said, my intent is probably all wrong here, but if it's valid, I cannot find any syntax examples on google..
go easy on me...:)
In the constructor's initialization-list:
B(int number, const Object& objRef) : A(number), m_obj(objRef)
{}
(Note, this is nothing to do with this being a subclass. You always need to use the initialization list in order to initialize a member variable that's a reference.)

C++: Passing reference of constructing object to constructed member objects?

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

Calling the constructor of the base class after some other instructions in C++

As far as I know it is not possible to call the constructor of the base class. The only way I know is this:
MyClass::MyClass(/* args */) : Base(/* args */)
{
// ...
}
but this would invoke the constructor at the beginning.
Is there any way to call it somewhere else in the constructor? Something like this:
MyClass::MyClass(/* args */)
{
// ... instructions
Base::Base(/* args */);
// ... other_instructions
}
According to this What are the rules for calling the superclass constructor? question I understand there is no way but I read here and I guessed it was possible, but if I try I get:
error: invalid use of 'class Base'.
Am I doing something wrong? Is it possible to do this some way or is there any other possible solution to this need?
Thanks!
EDIT: I understand I forgot a key point: the base class is part of a framework, and therefore it would be good not to have to modify it, if possible.
If the base class constructor takes at least one argument, you could use a helper function like this:
int DoStuffBeforeCtorAndForwardInt(int arg, Foo foo)
{
DoStuff(arg, foo);
return arg;
}
MyClass::MyClass(int arg, Foo foo)
: Base(DoStuffBeforeCtorAndForwardInt(arg, foo))
{
// ...
}
If you want to default-initialize the base class, you could use the copy-ctor to copy a default initialized base class instance:
Base DoStuffBeforeCtorAndReturnDefaultBase(int arg, Foo foo)
{
DoStuff(arg, foo);
return Base();
}
MyClass::MyClass(int arg, Foo foo)
: Base(DoStuffBeforeCtorAndReturnDefaultBase(arg, foo))
{
// ...
}
Or, if Base doesn't have to be the first base class, you could derive MyClass from a helper class:
MyClass::MyClass(/* ... */)
: DoStuffHelperClass(/* ... */),
Base(/* ... */)
{
// ...
}
All of the above require that the "stuff" you do does not depend on the object that's about to be initialized (i.e. the functions can't safely be member functions and you cannot safely pass this as an argument to them either).
That means you can do some logging or similar, but then again you could also do that after the base class has been initialized.
(EDIT except with the DoStuffHelperClass solution, you can of course have members in DoStuffHelperClass, access them and what not)
Although I have to say that I can't recall ever using/needing/wanting something like that. It's quite probable that there is another (preferable) solution for what you're trying to do.
Use the base-from-member idiom to run your code before the ctor of the "real" base class (which is Base):
struct Base {
Base(string, int);
};
struct DerivedDetail {
DerivedDetail() {
value = compute_some_value();
value += more();
value += etc();
other = even_more_code(value);
}
string value;
int other;
};
struct Derived : private DerivedDetail, Base {
Derived() : Base(value, other) {}
// In particular, note you can still use this->value and just
// ignore that it is from a base, yet this->value is still private
// within Derived.
};
This works even if you don't have actual members you want in DerivedDetail. If you give more specifics on what you must do before the Base's ctor, then I can give a better example.
The base class is always fully constructed before construction of your own class begins. If you need to make a change to the state of the base class, you have to do that explicitly after it has been constructed.
Example:
MyClass::MyClass()
{
// Implicit call to Base::Base()
int result = computeSomething();
Base::setResult(result);
// ...
}
Besides the already written solutions, you can also use a static constructor function and make the contructor of MyClass private.
class QtBase{
// ...
};
class MyClass : public QtBase{
public:
// copy ctor public
MyClass(MyClass const& other);
static MyClass Create(/*args*/){
// do what needs to be done
int idata;
float fdata;
// work with idata and fdata as if they were members of MyClass
return MyClass(idata,fdata); // finally make them members
}
static MyClass* New(/*args*/){
int idata;
float fdata;
// work with idata and fdata as if they were members of MyClass
return new MyClass(idata,fdata); // finally make them members
}
private:
// ctor private
MyClass(int a_idata, float a_fdata)
: idata(a_idata)
, fdata(a_fdata)
{}
int idata;
float fdata;
};
Now you would have to create instances of MyClass either as:
MyClass obj = MyClass::Create(/*args*/);
or
MyClass* ptr = MyClass::New(/*args*/);
no, because it will not be type safe.
consider you have: a class A and a variable A.var.
now consider B inherits from A, and uses var before A was initialized. you will get a run time error! the language wants to prevent this, thus superclass constructor must be initialized first.
No, you can't do it that way, as other have described in their previous answers.
Your only chance is composition, IOW that MyClass uses Base class as a member field:
class MyClass {
public:
/** the methods... */
private:
Base* _base;
};
so you can initialize _base later, when you have the needed info. I don't know if this can apply to your scenario, anyway.
No. It is not possible, because the order of constructor calls is strictly defined by the standard. Base class ctor has to be executed before the derive class ctor can be executed.

C++: References as constructor arguments, help

I have a base class(Base) whose constructor takes a reference as argument. In my derived class its constructor, I call the superclass-constructor and of course I need to pass a reference as argument. But I have to obtain that argument from a method of which the return type is by value...
I will give a short example:
class Base
{
public:
Base(MyType &obj) { /* do something with the obj */}
};
class Derived : public Base
{
public:
Derived(MyOtherType *otherType) :
Base(otherType->getMyTypeObj()) // <--- Here is the error because (see *)
{
// *
// getMyTypeObj() returns a value and
// the Base constructor wants a reference...
}
};
class MyOtherType
{
public:
MyType getMyTypeObj()
{
MyType obj;
obj.setData( /* blah, blah, blah... Some data */);
return obj; // Return by value to avoid the returned reference goes out of scope.
}
};
How can I solve this problem?
Change the Base class to:
class Base
{
public:
Base(const MyType &obj) { /* do something with the obj */}
};
Update: If you want to modify obj you cannot obviously have a const reference. In that case you can either:
1)Pass the parameter by value. That will have the overhead for the copy but avoid having to free it explicitly later.
2) Change MyOtherType::getMyTypeObj() to
MyType& MyOtherType::getMyTypeObj()
{
MyType* obj = new MyType();
obj->setData( /* blah, blah, blah... Some data */);
return *obj;
}
In this case, remember to delete the object after you are done with it.
Seriously? Your question has the answer in it. Change either the type of the parameter to the Base constructor, or the type of the return value of getMyTypeObj() so that the types are compatible.
The problem is caused by the GetMyTypeObj() returning a copy of 'obj', which is stack-based, so the compiler makes a temporary variable inside your constructor, the scope of which is just that Base() construction call.
It seems to me that there are two ways to solve this.
Change the Base constructor to accept a MyType object by value instead of by reference. This will copy the temporary object and solve scope problems.
Alternatively, you can make a copy of the MyType object in Derived and pass a reference to that.
class Derived : public Base
{
public:
Derived(MyOtherType *otherType) :
Base(m_myType) ,
m_myType(otherType->getMyTypeObj())
{
// ...
}
private:
MyType m_myType;
};
Option 1 is simpler and I would generally recommend it.
Option 2 is just in case some other constraint prevents you changing the Base constructor,