Han*_*esh 45 c++ constructor class object
在C++中,我想将对象定义为类的成员,如下所示:
Object myObject;
Run Code Online (Sandbox Code Playgroud)
但是,这样做会尝试调用它的无参数构造函数,它不存在.但是我需要在包含类完成初始化之后调用构造函数.像这样的东西.
class Program
{
public:
Object myObject; //Should not try to call the constructor or do any initializing
Program()
{
...
//Now call the constructor
myObject = Object(...);
}
}
Run Code Online (Sandbox Code Playgroud)
Jul*_*ian 24
存储指向Object而不是实际的指针Object
从而:
class Program
{
public:
Object* myObject; // Will not try to call the constructor or do any initializing
Program()
{
//Do initialization
myObject = new Object(...); // Initialised now
}
}
Run Code Online (Sandbox Code Playgroud)
不要忘记delete它在析构函数中.现代C++可以帮助您,因为您可以使用auto_ptr shared_ptr而不是原始内存指针.
bdo*_*lan 15
其他人已经使用原始指针发布了解决方案,但智能指针将是一个更好的主意:
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
};
Run Code Online (Sandbox Code Playgroud)
这避免了添加析构函数的需要,并且隐式禁止复制(除非你自己写operator=和MyClass(const MyClass &).
如果您想避免单独的堆分配,可以使用boost aligned_storage和placement new 来完成.未经测试:
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();
}
}
Run Code Online (Sandbox Code Playgroud)
或者,如果Object是可复制的(或可移动的),您可以使用boost::optional:
class MyClass {
boost::optional<Object> obj;
public:
MyClass() {
// ...
obj = Object(...);
obj->foo();
}
};
Run Code Online (Sandbox Code Playgroud)
你可以通过这个技巧完全控制对象的构造和销毁:
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;
};
};
Run Code Online (Sandbox Code Playgroud)
应用于您的样品:
class Program
{
public:
DefferedObject<Object> myObject; //Should not try to call the constructor or do any initializing
Program()
{
...
//Now call the constructor
myObject.Construct(....);
}
}
Run Code Online (Sandbox Code Playgroud)
这个解决方案的一大优点是它不需要任何额外的分配,并且正常分配对象内存,但是你可以控制调用构造函数。
如果您可以将其他初始化转移到构造函数中,您也可以重写代码以使用构造函数初始化器列表:
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*/)
{
...
}
};
Run Code Online (Sandbox Code Playgroud)
您需要注意,遵循这样的模式将导致您在构造函数中做大量工作,这反过来又导致需要掌握异常处理和安全性(作为从构造函数返回错误的规范方法)是抛出异常)。
如果您有权访问boost,则会提供一个被称为的方便对象boost::optional<>- 这可以避免动态分配的需要,例如
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;
};
Run Code Online (Sandbox Code Playgroud)