在子类中初始化父类的 const 成员
Initializing parent's const members in child class
我甚至不确定这是可能的,所以我想澄清一下。我有一个父类的const数组字符串,我希望它被初始化的子类,如:
class CParent{
CParent();
const char** strings;
};
和子类
class CChild:CParent{
CChild();
};
CChild::CChild()
: CParent::strings{
"First",
"Second"
}
{
CParent();
// some code
}
我需要这个,因为我将调用CParent的构造函数,在那里我需要使用字符串。它可以通过参数传递来完成,但我想知道这样的事情是否可能。
编辑:我在这里重写代码时忘记写一些东西,所以我宁愿复制粘贴它,这样我现在就不会忘记任何东西了。我在Andy Prowl的帮助下使用字符串和向量重写了它:
class CMenu {
public:
CMenu(std::vector<std::string> const& s);
protected:
std::vector<std::string> choicesStr;
};
CMenu::CMenu(std::vector<std::string> const & s) : choicesStr(s) {
// code code
}
class CGameTypeMenu : public CMenu {
public:
CGameTypeMenu();
};
CGameTypeMenu::CGameTypeMenu()
:CMenu(std::vector<std::string>("aaa","bbb")){ // This is where I
get some nasty errors
}
错误如下:
In file included from /usr/include/c++/4.7/vector:63:0,
from CMenu.h:13,
from CGameTypeMenu.h:11,
from CGameTypeMenu.cpp:8:
/usr/include/c++/4.7/bits/stl_uninitialized.h:77:3: required from ‘static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = const char*; _ForwardIterator = std::basic_string<char>*; bool _TrivialValueTypes = false]’
(5+ more similar lines follow)
按正确的方式做(此解决方案仅适用于c++ 11):
#include <vector>
#include <string>
class CParent
{
protected:
// ^^^^^^^^^^ Make sure your constructor is at least protected,
// or it will be inaccessible to derived classes
CParent(std::vector<std::string> const& s) : strings(s) { };
std::vector<std::string> strings;
// ^^^^^^^^^^^^^^^^^^^^^^^^ Use containers and classes from the C++ Standard
// Library rather than raw pointers
};
class CChild : public CParent
// ^^^^^^^^^^^^^^^^ I suppose you forgot this.
// Inheritance is private by
// default, which does not seem
// to be what you want
{
CChild();
};
CChild::CChild()
:
CParent({"First", "Second"}) // C++11 ONLY!
// ^^^^^^^^^^^^^^^^^^^
// Implicit construction of the vector of string
{
// some code
}
您可以让CChild
的构造函数调用CParent
的构造函数并将您的数组作为其参数传递。然后你可能会尝试这样做:
CChild() : CParent({ "First", "Second" }) { }
,它被称为大括号初始化,只有在c++ 11支持下才有可能。如果你需要c++ 03解决方案,你想继续使用const char*
存储字符串,然后:
class CParent {
public:
CParent(const char* s[]) : strings(s) { }
const char** strings;
};
class CChild : public CParent {
public:
CChild() : CParent(strings_) { }
private:
static const char* strings_[];
};
const char* CChild::strings_[] = { "First", "Second" };
请注意,由于strings_
是一个数组,这个const
成员必须在源文件中初始化。
虽然我建议你使用std::vector
代替c风格的数组和std::string
代替c风格的字符串。在这种情况下,代码可能像这样:
typedef std::vector<std::string> StringVector;
class CParent {
public:
CParent(const std::vector<std::string>& s) : strings(s) { }
const StringVector strings;
};
class CChild : public CParent {
public:
CChild()
: CParent(strings_) { }
private:
static const std::string s_[];
static const StringVector strings_;
};
const std::string CChild::s_[] = { "First", "Second" };
const StringVector CChild::strings_ =
StringVector(CChild::s_, CChild::s_ + sizeof(CChild::s_)/sizeof(std::string));
初始化基类const成员的唯一方法是在派生类构造函数的初始化列表中将初始化实参传递给基类的构造函数,基类构造函数使用这些实参初始化其初始化列表中的const成员。
在任何构造函数(传递初始化列表)内部,任何成员(派生成员或基成员)都已经构造(默认值不显式),const不能再更改。
对CParent
成员进行成员初始化的唯一方法是通过适当的CParent
构造函数。
protected
或public
,那么你可以在子构造函数中通过赋值初始化父成员。
这个方法当然是不可能的,如果成员是真正的const
,即
const char ** const strings;
但是正确的方法是保持父成员私有,并提供一个合适的父构造函数。
- 不允许运算符 const 参数调用 const 成员函数
- c++ 是否保证标头初始化的静态 const 成员跨编译单元和库共享单个实例?
- 在类声明中初始化 const 成员变量时在调试模式下出现异常
- 如何避免将 const 和非 const 成员函数输入到模板中的代码重复
- 初始化 const 成员的正确方法
- 使用 Boost 对具有 const 成员的类进行序列化
- 非常量调用 const 成员函数失败,只读位置C++
- PIMPL类的设置应该是const成员函数
- 与其他静态const成员初始化静态常量成员
- decltype 不会推断 const 对象的 const 成员
- 如何初始化不是静态的const成员
- 如何使用常量变量初始化类的 const 成员变量
- 使用模板参数初始化静态 const 成员
- 与const成员配对的向量
- 通过参考const成员通过参考时,尝试引用已删除的函数
- const成员初始化之前的用法是GCC和Clang的这种预期行为
- 通过const成员变量访问内联函数
- 与const成员一起安排新的和班级的分配
- 在const函数中调用非CONST成员的非const函数
- 为什么即使对于 "copy on write" 的 const 成员函数也返回一个代理类?