0

我什至不确定这是否可能,所以我想澄清一下。我有一个带有 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)
4

4 回答 4

5

以正确的方式进行(此解决方案仅适用于 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
}
于 2013-03-07T12:46:01.200 回答
1

初始化基类的const成员的唯一方法是将初始化参数传递给派生类构造函数的初始化列表中的基类的构造函数,而基构造函数拿这个参数来初始化他的初始化列表中的const成员.

“内部”任何构造函数(传递初始化列表)任何成员(派生或基)已经(默认不显式)构造,并且 const 不能再更改。

于 2013-03-07T13:03:12.123 回答
1

您可以让构造函数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));
于 2013-03-07T13:17:19.470 回答
0

成员初始化成员的唯一方法CParent是通过适当的CParent构造函数。

作为一种解决方法,您可以通过子构造函数中的赋值来初始化父成员,如果父成员是可访问的,即protectedpublic.

如果成员是真的,这种解决方法当然是不可能的const,即

const char ** const strings;

但正确的方法是保持父成员私有并提供适当的父构造函数。

于 2013-03-07T12:49:50.387 回答