C++ 在派生类中初始化超类';s构造函数
MemRef是一个简单的类,用于指向它不拥有的内存 基类: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)
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>,就不可能实现你想要的,因为
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++所规定的初始化顺序与所需的相反, 您可以从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_列表)使用这些值”。