7 に答える
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?
私はそのために完全にゴミ箱に入れられると思います(すべての発煙に行く前に最後まで読んでください)が...ウィンドウのコンストラクターが決してスローしないと仮定します:
void MyClass::init()
{
obj::~Window(); // destroy the object
new (&obj) Window(...); // construct the object
};
私はもちろん、コンストラクターのnot throw要件を強調します。それがスローされたかのように、非常に泥だらけの状況が残されます: のデストラクタは、オブジェクトが生きていて、キックまたはトラッシュされているかどうかに関係なくMyClass
、のデストラクタを呼び出します。Window
構築に失敗し、後者の場合、未定義の動作が発生します。
もちろん、典型的なことはこのようになりますstd::unique_ptr<Window>
が、明らかに状況がそれを義務付けていない動的割り当てのハードルがあります...
したがって、ライブラリBoost.Optionalを使用する方がよいでしょう。
class MyClass
{
public:
private:
boost::optional<Window> obj;
};
構文呼び出しはポインターに似ています。
obj->foo();
しかし、1 つの利点は、より安全なセマンティクスでインプレースの破壊/構築ができることです。破壊は簡単です:
// both call ~Window() if an instance had been constructed
obj.reset();
obj = detail::none_t();
構築にはTypedInPlaceFactoryを使用します。そして割り当てについても...もちろん、前のインスタンス(存在する場合)を最初にクリアします:
void MyClass::init(Arg1 arg1, Arg2 arg2)
{
obj = boost::in_place<Window>(arg1, arg2);
}
主な利点は、構築中に例外が発生した場合でも、optional
オブジェクトはunitialized
完全に実行可能な状態のままになるため、未定義の動作を恐れる必要がないことです。
つまり、基本的には、動的に割り当てられたオブジェクトがスマート ポインターによって所有されているようなものです...オブジェクトが動的に割り当てられないという魔法を除いて、「通常の」オブジェクトとまったく同じパフォーマンスが保証されます:)
コピーできないハードルが InPlaceFactory 作成の背後にある理由の 1 つであることを付け加えておきます。
クラスメンバーの初期化は、次の例のようにクラスコンストラクターで実行する必要があります。
class MyClass
{
public:
MyClass(/* constructor params */);
private:
Window m_obj; // Hasn't copy constructor
};
MyClass::MyClass(/* constructor params */) : m_obj(/* constructor params */)
{
}
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();
Window
コピー コンストラクターがない場合、クラスの別のオブジェクトをそれに割り当てることはできませんWindow
。obj
初期化リストを使用するコンストラクターからのみ初期化できますMyClass
。例えば:
class MyClass
{
Window obj; // Hasn't copy constructor
public:
MyClass()
: obj(/*constructor params*/)
{
/*...*/
}
}