2013-11-27 237 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

相關問題