C++ 在派生类中初始化超类';s构造函数

C++ 在派生类中初始化超类';s构造函数,c++,inheritance,constructor,derived-class,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)

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\u 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);
};
加载的\u MemRef创建CTOR时遇到问题。在调用MemRef的ctor之前,我必须先将调用者提供的内存复制到\u内存中;否则,MemRef无法检索有效的\u memory.c\u str()。但我的理解是,在初始化加载的成员之前,必须首先调用MemRef(\u 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行如上图所示;下一行设置\u len,不会被标记,尽管编译器可能已退出。)


正确的方法是什么?

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

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

您实际上不需要在初始值设定项中设置内容。您可以在构造函数的主体中执行此操作:

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

如果你的基类有代码> const siZext LeNe/Cuff>,就不可能实现你想要的,因为 const 成员需要初始化器,而C++所授权的初始化顺序与你需要的相反。

< P>你不需要在初始化器中设置东西。您可以在构造函数的主体中执行此操作:

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\u t\u len
,就不可能实现您想要的,因为
const
成员需要初始值设定项,C++所规定的初始化顺序与所需的相反,

您可以从 LoADDyMeMeRef> /Cudio>构造函数(即<<代码>保护< /代码>)中更改<代码> 您可以给
MemRef
一个(
protected
?)成员函数来更改其指向的位置,并从
Loaded\u 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() )
    {}
};

您只需从加载的
MemRef
构造函数的主体中更改
\u ptr
\u len
(因为它们受
保护)

您可以给
MemRef
一个(
protected
?)成员函数来更改其指向的位置,并从
Loaded\u 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() )
    {}
};

为什么
Loaded_MemRef
的构造函数如此怪异?@KerrekSB:一个用于字符串引用,一个用于空终止的c字符串,一个用于缓冲区(无空终止,需要长度)。为什么
Loaded_MemRef
的构造函数如此怪异?@KerrekSB:一个用于字符串引用,一个用于空终止的c字符串,一个用于缓冲区(无空终止,需要长度)。您所说的常量也适用于常量ptr吗?是的;但您的
\u ptr
不是那种
常量(这没有问题)-有问题的是
const-char*const-ptr
你所说的const-len也适用于const-ptr吗?是的;但是你的
\u-ptr
不是那种
const
(没有问题)-有问题的是
const-char*const\ptr
使用C++11的std::move()的好例子。我不清楚是否需要大括号,或者是否可以同样好地使用括号?之所以需要大括号,是因为C++11示例没有为
struct
定义构造函数。括号表示“使用这些参数调用构造函数”;大括号表示“使用这些值初始化结构(或std::initializer\u列表)的成员”。使用C++11的std::move()的一个很好的例子。我不清楚你的大括号是必需的,还是可以同样好地使用paren?大括号是必需的,因为C++11示例没有为
结构定义构造函数
。括号中说“使用这些参数调用构造函数”;大括号中说“初始化结构的成员”(或一个std::initializer_列表)使用这些值”。