I have some class(Window) without copy constructor (it's private). I can't understand how to init var of this class in my own class:
class MyClass
{
Window obj; // Hasn't copy constructor
public:
void init()
{
obj = Window(/* constructor params */); // [error]
obj(/* constructor params */); // [error]
}
}
Error 1: initializing argument 1 of ‘Window::Window(WindowHandle, const sf::WindowSettings&)’
Error 2: ‘NonCopyable& NonCopyable::operator=(const NonCopyable&)’ is private
But it works in this way:
Window obj(/* constructor params */);
Use an initializer list:
class MyClass
{
Window obj; // Hasn't copy constructor
public:
MyClass() :
obj(/* constructor params */)
{
}
}
This goes for references, too. You can assign any member variable in an initializer list. It only works in the constructor, though.
If you want it to work outside a constructor, you need to use a pointer:
class MyClass
{
Window *obj;
public:
void init()
{
obj = new Window(/* constructor params */);
}
}
Be sure to deallocate obj using delete in your deconstructor (and make the deconstructor virtual if necessary).
Your MyClass needs a constructor to initialize the obj member.
class MyClass
{
private:
Window obj;
public:
MyClass() : obj(/* constructor params */) // This is an initializer list
{}
};
If you need the init() function, and the Window object provides its own
init() function of some sort, you can do this:
class MyClass
{
private:
Window obj;
public:
void init()
{
obj.init(/* init params */); // Window's own init() function
}
};
If the Window class does not have anything like an init() function, you can use the heap (not recommended unless you absolutely have to):
class MyClass
{
private:
// Alternatively, we can use a smart pointer here and avoid
// managing memory ourselves.
Window* obj;
public:
MyClass() : obj(0) {}
~MyClass() { uninit(); }
void init()
{
uninit();
obj = new Window(/* constructor params */);
}
void uninit()
{
if(obj != 0)
{
delete obj;
obj = 0;
}
}
};
If the Window class declares a private copy constructor and/or copy assignment operator, then you cannot assign a new Window instance to obj.
If your copy constructor is private the class does have a copy constructor. It seems your class has bothy copy ctor and assignment op as private, which explains the second error message. The first error message has something to do with the WindowHandle class, which you haven't shown.
To make much more sense of this, we'd need to see the Window class too - does it (for example) have a default constructor?
I suppose I'm going to get thoroughly trashed for that (read till the end before going all fuming) but... assuming the constructor of windows never throws:
void MyClass::init()
{
obj::~Window(); // destroy the object
new (&obj) Window(...); // construct the object
};
I shall of course underline the not throw requirement of the constructor as if it throws you'll be left with a very muddy situation: the destructor of MyClass will call the destructor of Window regardless of whether or not the object is alive and kicking or trashed because of a failed construction, and in the latter case you get undefined behavior.
Of course, a typical thing will thus be std::unique_ptr<Window> but we have the hurdle of dynamic allocation where clearly the situation does not mandate it...
So you'd be better off using a library: Boost.Optional.
class MyClass
{
public:
private:
boost::optional<Window> obj;
};
The syntax invocation is similar to a pointer:
obj->foo();
But the one benefit is that you get inplace destruction / construction with safer semantics. Destruction is easy:
// both call ~Window() if an instance had been constructed
obj.reset();
obj = detail::none_t();
For construction use a TypedInPlaceFactory. And for assignment too... which of course clears up the previous instance (if any) first:
void MyClass::init(Arg1 arg1, Arg2 arg2)
{
obj = boost::in_place<Window>(arg1, arg2);
}
The main advantage is that if any exception is now encountered during construction, the optional object is left in the unitialized state, which is perfectly viable, and thus you need not fear undefined behavior.
So basically it's like having a dynamically allocated object owned by a smart pointer... except that the magic is that the object is not dynamically allocated, thus guaranteeing the very same performances that a "normal" object :)
I should add that the non-copyable hurdle is one of the reason behind the InPlaceFactory creation.
The whole point is not letting you clone it.
Initialize like this: Window obj(parameters of other constructor, not the copy one)
or
Window &obj = somefunctionConstructingSuchAWindow();
If Window doesn't have a copy constructor, you cannot assign another object of class Window to it. You can initialize obj only from the constructor of MyClass using an initializer list. For example:
class MyClass
{
Window obj; // Hasn't copy constructor
public:
MyClass()
: obj(/*constructor params*/)
{
/*...*/
}
}
The initialization of class members should be done on class constructor like on the following example:
class MyClass
{
public:
MyClass(/* constructor params */);
private:
Window m_obj; // Hasn't copy constructor
};
MyClass::MyClass(/* constructor params */) : m_obj(/* constructor params */)
{
}
Related
Probably I was not clear
class Class {
int member;
otherClass otherClass_member;
Class() { ... }
Class(int x) { ... }
Class(const Class &other) { ... }
Class(Class &&other) : member(other.member), otherClass_member(std::move(other.otherClass_member)) {
member=other.member;
otherClass_member=std::move(other.otherClass_member);
other.member=0;
//other.otherClass_member = ???;
}
~Class() { ... }
I have 3 questions:
what do this do member(other.member), otherClass_member(std::move(other.otherClass_member))?
does it need this member=other.member; otherClass_member=std::move(other.otherClass_member);? I'm asking that because some tutorials put and some don't.
if I have the code above, how should I treat this string other.otherClass_member = ???;
what do this do member(other.member),
otherClass_member(std::move(other.otherClass_member))?
These initialize members of the object you are constructing. Using std::move() allows to steal resources of the existing object other if otherClass has move constructor.
does it need this member=other.member;
otherClass_member=std::move(other.otherClass_member);?
Not only does not it need this, but it would be a mistake because you would be moveing other.otherClass_member twice. You could have these statements instead of the above initialization, but this is an inferior choice and only possible if otherClass has a default constructor.
if I have the code above, how should I treat this string
other.otherClass_member = ???;
You don't need it at all. Move constructor of otherClass should handle this (or copy constructor if move constructor does not exist).
I want to call a constructor of a member object in the owners constructor, but can not construct the member object in the initializer-list because of dependencies. How can I call the constructer after my initializations? I would really like to not use an init method
No.
You cannot call the constructor of a member class outside the initializer list.
PS: Even if you don't call it yourself in the initializer list, then the compiler will do it implicitly.
If you cannot call it in the initializer list, and you don't want to use an init-like method, then re-think your design/approach.
You have two options: either use dynamic storage, or placement new.
The first one is obvious (as pointed out in comments, you can use unique_ptr). If you want to avoid this, you might try placement new with std::aligned_union as storage:
class SomeClass { ... };
class Owner
{
public:
Owner()
{
m_ptr = new(&m_storage) SomeClass();
}
~Owner()
{
m_ptr->~SomeClass();
}
private:
std::aligned_union<0, SomeClass> m_storage;
SomeClass* m_ptr;
};
Note: in this case, you are responsible to calling destructor of the object, as shown above.
You can wrap m_ptr with a unique_ptr (with a deleted which only calls a destructor) to avoid this:
struct DtorDeleter
{
template<typename T>
void operator ()(T* ptr) { ptr->~T(); }
};
std::unique_ptr<SomeClass, DtorDeleter> m_ptr; // no need to call destructor manually
You can use an union for this (C++11 needed):
#include <new>
class Foo {
public:
Foo(int a) { }
};
class Bar {
public:
Bar() {
new(&m_foo) Foo(42); // call the constructor
// you can use m_foo from this point
}
~Bar() {
m_foo.~Foo(); // call the destructor
}
private:
union { // anonymous union
Foo m_foo;
};
};
Note that you need to explicitly call the destructor of m_foo at ~Bar().
want to call a constructor of a member object in the owners constructor, but can not construct the member object in the initializer-list because of dependencies
You might modify your class to have correct dependency order, and maybe use delegating constructor:
So turning:
struct S
{
S(/*..*/) : /*m1(data), m2(data),*/ data(/*..*/) // Issue, m1, m2 constructed before data
{
ComplexData2 data2 = Query();
m1.init(data, data2.someField1); // Doesn't like init method
m2.init(data, data2.someField2); // Doesn't like init method
}
Member1 m1; // Cannot be const with init method :/
Member2 m2; // Cannot be const with init method :/
ComplexData data;
};
into
struct S
{
S(/*..*/) : S(Query() /*, ..*/) {}
// private: // probably private
S(const ComplexData2& data2 /*, ..*/) :
data(/*..*/),
m1(data, data2.someField1),
m2(data, data2.someField2)
{
}
public:
ComplexData data; // Before m1, m2 for dependencies.
/*const*/ Member1 m1; // Can be const
/*const*/ Member2 m2; // Can be const
};
I'm trying to write a program for my Arduino, but I don't understand something that's happening when passing an Item object to another Holder object. I've constructed a simple example:
class Item {
public:
int property;
Item() {
Serial.println("parameterless constructor called");
this->property = 2;
}
Item(int property) {
this->property = property;
Serial.println("right constructor called");
}
};
class Holder {
public:
Item someitem;
Holder(Item& someitem) {
this->someitem = someitem;
}
};
void setup() {
Serial.begin(9600);
Item someitem = Item(1);
Serial.println(someitem.property);
Holder hold = Holder(someitem);
Serial.println(hold.someitem.property);
}
void loop() {
}
The output on the console is:
right constructor called
1
parameterless constructor called
1
I don't understand why the parameterless constructor is called in the first place (I'm not creating a new object to my understanding), and also why it does neither change the current object nor makes a new one. Leaving out the parameterless constructor is prevented by the compiler.
You forgot how we initialize class members in C++ - member initializer lists:
Holder(Item const& someitem) : someitem(someitem) {}
In your code, someitem is default-constructed first (before execution enters the {} block of the constructor), then you're using assignment operator.
Copy constructor is not invoked (and it can't be on already constructed object).
In C++, I want to define an object as a member of a class like this:
Object myObject;
However doing this will try to call it's parameterless constructor, which doesn't exist. However I need the constructor to be called after the containing class has done some initialising. Something like this.
class Program
{
public:
Object myObject; //Should not try to call the constructor or do any initializing
Program()
{
...
//Now call the constructor
myObject = Object(...);
}
}
Store a pointer to an Object rather than an actual Object
thus:
class Program
{
public:
Object* myObject; // Will not try to call the constructor or do any initializing
Program()
{
//Do initialization
myObject = new Object(...); // Initialised now
}
}
Don't forget to delete it in the destructor. Modern C++ helps you there, in that you could use an auto_ptr shared_ptr rather than a raw memory pointer.
Others have posted solutions using raw pointers, but a smart pointer would be a better idea:
class MyClass {
std::unique_ptr<Object> pObj;
// use boost::scoped_ptr for older compilers; std::unique_ptr is a C++0x feature
public:
MyClass() {
// ...
pObj.reset(new Object(...));
pObj->foo();
}
// Don't need a destructor
};
This avoids the need to add a destructor, and implicitly forbids copying (unless you write your own operator= and MyClass(const MyClass &).
If you want to avoid a separate heap allocation, this can be done with boost's aligned_storage and placement new. Untested:
template<typename T>
class DelayedAlloc : boost::noncopyable {
boost::aligned_storage<sizeof(T)> storage;
bool valid;
public:
T &get() { assert(valid); return *(T *)storage.address(); }
const T &get() const { assert(valid); return *(const T *)storage.address(); }
DelayedAlloc() { valid = false; }
// Note: Variadic templates require C++0x support
template<typename Args...>
void construct(Args&&... args)
{
assert(!valid);
new(storage.address()) T(std::forward<Args>(args)...);
valid = true;
}
void destruct() {
assert(valid);
valid = false;
get().~T();
}
~DelayedAlloc() { if (valid) destruct(); }
};
class MyClass {
DelayedAlloc<Object> obj;
public:
MyClass() {
// ...
obj.construct(...);
obj.get().foo();
}
}
Or, if Object is copyable (or movable), you can use boost::optional:
class MyClass {
boost::optional<Object> obj;
public:
MyClass() {
// ...
obj = Object(...);
obj->foo();
}
};
You can fully control the object construction and destruction by this trick:
template<typename T>
struct DefferedObject
{
DefferedObject(){}
~DefferedObject(){ value.~T(); }
template<typename...TArgs>
void Construct(TArgs&&...args)
{
new (&value) T(std::forward<TArgs>(args)...);
}
public:
union
{
T value;
};
};
Apply on your sample:
class Program
{
public:
DefferedObject<Object> myObject; //Should not try to call the constructor or do any initializing
Program()
{
...
//Now call the constructor
myObject.Construct(....);
}
}
Big advantage of this solution, is that it does not require any additional allocations, and object memory allocated as normal, but you have control when call to constructor.
Another sample link
If you have access to boost, there is a handy object that is provided called boost::optional<> - this avoids the need for dynamic allocation, e.g.
class foo
{
foo() // default std::string ctor is not called..
{
bar = boost::in_place<std::string>("foo"); // using in place construction (avoid temporary)
}
private:
boost::optional<std::string> bar;
};
You may also be able to rewrite your code to use the constructor initializer list, if you can move off the other initialization into constructors:
class MyClass
{
MyObject myObject; // MyObject doesn't have a default constructor
public:
MyClass()
: /* Make sure that any other initialization needed goes before myObject in other initializers*/
, myObject(/*non-default parameters go here*/)
{
...
}
};
You need to be aware that following such a pattern will lead you to a path where you do a lot of work in constructors, which in turn leads to needing to grasp exception handling and safety (as the canonical way to return an error from a constructor is to throw an exception).
You can use a pointer (or a smart pointer) to do that. If you do not use a smart pointer, do make sure that your code free memory when the object is deleted. If you use a smart pointer, do not worry about it.
class Program
{
public:
Object * myObject;
Program():
myObject(new Object())
{
}
~Program()
{
delete myObject;
}
// WARNING: Create copy constructor and = operator to obey rule of three.
}
A trick that involves anonymous union and placement new
this is similar to jenkas' answer but more direct
class Program
{
public:
union{
Object myObject;
}; //being a union member in this case prevents the compiler from attempting to call the (undefined) default constructor
Program()
{
...
//Now call the constructor
new (&myObject) Object(...);
}
~Program()
{
myobject.~Object(); //also make sure you explicitly call the object's destructor
}
}
however the catch is that now you must explicitly define all the special member functions as the compiler will delete them by default.
Can you please tell me if it is possible to call object constructor manually? I know it's wrong and I would never do something like that in my own code and I know I can fix this problem by creating and calling initialization function, however the problem is that I stumbled at a case where there are thousands of lines of code in object's and its parents' constructors...
class MyClass()
{
MyClass() { }
virtual ~MyClass();
void reset()
{
this->~MyClass();
this->MyClass::MyClass(); //error: Invalid use of MyClass
}
};
You can still move construction/destruction into separate functions and call those directly. i.e.
class MyClass {
public:
MyClass() { construct(); }
~MyClass() { destruct(); }
void reset() {
destruct();
construct();
}
private:
void construct() {
// lots of code
}
void destruct() {
// lots of code
}
};
You could use placement new syntax:
this->~MyClass(); // destroy
new(this) CMyClass(); // construct at the same address
A constructor is called using placement new
new (address) MyClass();
This constructs a MyClass in an empty space at address.
Would never do this inside the class though!
Edit
If you already have an object of the right type, and want to assign it default values, an alternative is
*this = MyClass();
which creates a new object with default values and assigns that value to your existing object.