在派生类的构造函数中初始化超类

时间:2013-11-27 22:18:44

标签: c++ inheritance constructor derived-class

MemRef 是一个简单的类,指向它不拥有的一些内存。

基类:

class MemRef {

protected:
    const char *               _ptr;
    std::size_t                _len;

public:
    // Constructors
    MemRef()                        : _ptr(0), _len(0) {}
    MemRef(const string& s)         : _ptr(s.c_str()), _len(s.length()) {}
    MemRef(const char* b, size_t l) : _ptr(b), _len(l) {}
};

Loaded_MemRef 是一个子类,它提供自己的缓冲区,当不能信任调用者提供在 MemRef 的生命周期内保持分配和未更改的内存时。 Loaded_MemRef 将数据复制到它控制的秘密缓冲区中,然后指向它,允许我将其视为简单的 MemRef

派生类:

class Loaded_MemRef : public MemRef {

private:
    const string _memory;

public:
    Loaded_MemRef(const string& s) : ??? {}
    Loaded_MemRef(const char*);
    Loaded_MemRef(const char*, const size_t);
};

我在为 Loaded_MemRef 创建ctors时遇到问题。在调用 MemRef 的ctor之前,我必须将 _memory 复制到调用者提供首先的内存中;否则 MemRef 无法检索有效的 _memory.c_str()。但我的理解是,在初始化 Loaded_MemRef 的成员之前,必须首先调用 MemRef(_memory)。所以我尝试了这个:

Loaded_MemRef(const string& str) :
    MemRef(),            // get this over with
    _memory(str),                  // copy str into _memory
    MemRef::_ptr(_memory.c_str()), // (LINE 108) "reach up into" MemRef and set its protected members
    MemRef::_len(_memory.length())
{}

抱怨:

MemRef.cpp: In constructor 'Loaded_MemRef::Loaded_MemRef(const std::string&)':
MemRef.cpp:108: error: expected class-name before '(' token
MemRef.cpp:108: error: expected '{' before '(' token

(第108行显示在上面;下一行,设置 _len ,不会被标记,尽管编译器可能会被保释。)

正确的方法是什么?

3 个答案:

答案 0 :(得分:2)

你真的不需要在初始化器中设置东西。你可以在构造函数的主体中完成它:

Loaded_MemRef(const string& str) :
    MemRef(),            // get this over with
    _memory(str),        // copy str into _memory
{
    _ptr = _memory.c_str();
    _len = _memory.length();
}

如果你的基类有const size_t _len,就不可能实现你想要的,因为const成员需要初始化器,而C ++强制要求的初始化顺序与你需要的相反。

答案 1 :(得分:2)

您可以从_ptr构造函数的正文中更改_lenLoaded_MemRef(因为它们是protected)。

你可以给MemRef一个(protected?)成员函数来改变它所指向的位置,并使用Loaded_MemRef构造函数体中的那个。

或者,如果你真的,真的想/需要初始化MemRef一次,你可以将string移动到在基类之前初始化的那一件事:另一个基类(声明virtual或更早版本。

仅使用C ++ 03:

struct Loaded_MemRef__Base
{
    std::string _memory;
    explicit Loaded_MemRef__Base(const std::string& str)
      : _memory(str) {}
};

class Loaded_MemRef
    : private Loaded_MemRef__Base,
      public MemRef
{
public:
    Loaded_MemRef(const string& str) :
        Loaded_MemRef__Base( str ),
        MemRef( _memory.data(), _memory.length() )
    {}
};

使用C ++ 11功能:

struct Loaded_MemRef__Base
{
    std::string _memory;
};

class Loaded_MemRef
    : private Loaded_MemRef__Base,
      public MemRef
{
public:
    Loaded_MemRef(std::string str) :
        Loaded_MemRef__Base{ std::move(str) },
        MemRef( _memory.data(), _memory.length() )
    {}
};

答案 2 :(得分:1)

您无法在派生类初始化列表中初始化超类的成员,即使它们受到保护。解决方案是使用超类的构造函数。