2012-08-08 75 views
1

我已经定义了一个成员变量,如下所示。由于变量不会被传递,所以我决定在这里使用scoped_ptr而不是shared_ptr。推迟boost的初始化:: scoped_ptr

class ClassName 
{ 
public: 
    ClassName() 
    { 
     Initialize(); 
    } 

    virtual void Initialize() = 0; 

protected: 
    boost::scoped_ptr<int> m_scpInt; 
} 

class ClassNameB : public ClassName 
{ 
public: 
    virtual void Initialize() 
    { 
     m_scpInt.reset(new int(100)); 
    } 
} 

由于scoped_ptr的极限,如果我决定推迟变量的初始化在以后的时间,我得到的唯一的选择是调用复位。

Q1>这是一个很好的做法吗?

Q2>否则,是否有更好的解决方案?

谢谢

///更新-1 ///

这是我真正想做的事情。

我想强制每个派生类定义一个名为Initialize的函数,然后调用函数InitializeVarA和InitializeVarB。如您所示,我们不能在构造函数中调用虚函数。

class ClassName 
{ 
public: 
    ClassName() 
    { 
    }  
    virtual void Initialize() 
     { 
      InitializeVarA(); 
      InitializeVarB(); 
     }   
    protected: 
     virtual void InitializeVarA() {} 
     virtual void InitializeVarB() {} 
} 

class ClassNameB : public ClassName 
{ 
public: 
    ClassNameB() 
    { 
    }  
    virtual void Initialize() 
     { 
      InitializeVarA(); 
      InitializeVarB(); 
     }   
    protected: 
     virtual void InitializeVarA() {} 
     virtual void InitializeVarB() {} 
} 

ClassNameB cb; 
cb.Initialize(); 

我有比这更好的解决方案吗?

+2

好像'scoped_ptr'是不是真的适合你的正确的事在这种情况下使用。 'std :: unique_ptr'有什么问题? – 2012-08-08 14:50:31

回答

4

这是一个很好的做法吗?

使用reset来重置范围指针是好的。

尝试通过从基类的构造函数调用虚函数来初始化派生类不仅是不好的做法;这是不对的。此时,对象的动态类型是基类,并且该函数是纯虚拟的,因此调用它会导致未定义的行为。

即使您将其设为非纯文本,您仍然无法在该位置调用派生类的覆盖,因此指针将不会被重置。

否则,有没有更好的解决方案?

你可以在派生类的构造函数,这是基类的后立即调用做到这一点:

class Base { 
public: 
    Base() { /* don't call any virtual functions here */ } 

protected: 
    boost::scoped_ptr<int> p; 
}; 

class Derived : public Base { 
public: 
    Derived() { 
     p.reset(new int(100)); 
    } 
}; 

或者你也可以通过分配的内存基类的构造函数和初始化从指针。这有点危险 - 你必须确保在任何可能抛出异常的内容之前立即初始化指针,否则内存可能会泄漏。

class Base { 
public: 
    Base(int * p) : p(p) {} 

private: // doesn't need to be protected now 
     // (unless something else in the derived class needs access) 
    boost::scoped_ptr<int> p; 
}; 

class Derived : public Base { 
public: 
    Derived() : Base(new int(100)) {} 
}; 

在C++ 11,你可以使用unique_ptr,这是可移动的,以避免泄漏的风险:

class Base { 
public: 
    typedef std::unique_ptr<int> ptr; 
    Base(ptr && p) : p(p) {} 

private: 
    ptr p; 
}; 

class Derived : public Base { 
public: 
    Derived() : Base(ptr(new int(100))) {} 
}; 
+0

首先感谢您指出“在施工过程中不要调用虚拟功能”。请参阅我更新的帖子。谢谢 – q0987 2012-08-08 15:17:43