推迟boost :: scoped_ptr的初始化

时间:2012-08-08 14:41:45

标签: c++ boost

我已经定义了一个成员变量,如下所示。由于变量不会被传递,所以我决定在这里使用scoped_ptr而不是shared_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的限制,如果我决定在稍后的时间推迟变量的初始化,我得到的唯一选择是调用reset。

Q1&GT;这是一个好习惯吗?

Q2&GT;否则,有更好的解决方案吗?

谢谢

///更新了-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();

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

1 个答案:

答案 0 :(得分: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))) {}
};