2013-11-27 199 views
1

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。我必须复制到_memory调用者提供的内存第一个,之前致电MemRef的ctor;否则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,没有得到标记,虽然也许编译器保释。 )

什么是这样做的方法是什么?

+0

为什么'Loaded_MemRef'这种怪异的构造函数? –

+0

@KerrekSB:一个用于字符串引用,一个用于空终止的C字符串,一个用于缓冲区(无空终止,需要长度)。 – Chap

回答

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授权++初始化顺序相反你需要什么。

+0

是否你说的** const _len **也适用于** const _ptr **? – Chap

+0

是的;但你的'_ptr'不是*那种'const'(它没有问题) - 有问题的将是'const char * const _ptr' – anatolyg

+1

“不可能”没有一点诡计,也就是说。 – aschepler

1

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

2

您可以从Loaded_MemRef构造函数的主体中更改_ptr_len(因为它们是protected)。

您可以给MemRef a(protected?)成员函数更改指向的位置,并使用构造函数主体中的成员函数。

或者,如果你真的想/需要初始化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()) 
    {} 
}; 
+0

使用C++ 11的std :: move()的好例子。我不清楚你的支架是否需要,或者是否可以使用同样好的支架? – Chap

+1

因为C++ 11的例子没有定义'struct'的构造函数,所以需要大括号。括号说“用这些论点调用构造函数”;大括号说“用这些值初始化struct(或std :: initializer_list)的成员”。 – aschepler

相关问题