【问题标题】:const char array multiple initialization c++const char数组多重初始化C++
【发布时间】:2016-11-21 21:59:13
【问题描述】:

我在Base 类中有一个const char 数组。

static const char *_myArray[10];

我创建了一个子 Child1 类的 CPP 文件,并且可以使用以下语法初始化 _myArray[10]

const char *Base::_myArray[10] = {"red", "green", "blue"};

我创建了另一个子名称Child2,我需要使用{"pink", "yellow", "brown"} 值初始化这个数组。

我在Child2 中进行了类似的尝试,但是,它无法使用这种方式初始化数组。它给出了多重初始化存在问题的编译错误。

我正在使用我的基类实例中的这个数组(从派生类进行强制转换),并且应该从派生类填充数据(因为数据可能因子类而异)。

解决这个问题的正确方法是什么? 非常感谢您的支持。

提前谢谢你!

【问题讨论】:

  • 你知道不会有两个_myArrays 吗?对于所有派生类的所有实例都是一样的。
  • 不要将其设为静态或将数组声明移动到子类中。
  • 你真正想要达到什么目的?
  • @RichardHodges:我的意图是使用我的基类中的一个数组(基类拥有该受保护的数组)。但是,数组数据是动态的,将由我的派生类确定。如果有多个子类,就会出现问题。
  • @mirzapinku 对于同一类的每个对象,数组的内容是否相同? IE。它是标识一种类型,还是对象的每个实例都不同?

标签: c++ inheritance char constants


【解决方案1】:

您的问题是static 关键字。这意味着该类的所有实例共享一个数组(如果声明为 public,则该数组甚至可以在没有任何实例的情况下访问)。因此,您使用{"red", "green", "blue"} 初始化数组,之后,由于数组为const,因此无法再进行更改。然后你尝试使用{"pink", "yellow", "brown"} 再次初始化它,这将导致错误。

为什么这个数组必须是静态的?删除静态并在构造函数的初始化列表中进行初始化。

这是此方法的正确语法:

Base::Base() : _myArray{"red", "green", "blue"} 
{
    // Constructor here
}

我还注意到一个问题,您将这个一维数组视为二维的。数组的每个单元格只能存储一个字符,而不是 C 字符串。您可以使用二维数组或std::strings 数组来解决这个问题。

【讨论】:

  • 我尝试像 Child1 :: Chiled1 一样初始化:_myArray({"red", "green", "blue"}) { } Child2 :: Chiled2 : _myArray({"Black", " white", "brown"}) { } 但显示语法错误..
  • 编辑答案以包含必要的信息
  • Base::Base() : _myArray{"red", "green", "blue"} { // 此处的构造函数 } 这对于 base 来说是可以的。但是,如果想从像 Child::Child() 这样的子级执行此操作:_myArray{"red", "green", "blue"} { // Constructor here } 则会出现错误。
  • 当然,如果数组是私有的,这将不起作用。如果数组受到保护,这也将作为孩子的可访问成员。如果您愿意在问题中提供课程的必要部分,则可以更好地回答。
  • 当然数组是受保护的。下面是类 - class MyBaseClass { protected: MyBaseClass();受保护:枚举类 PConst{ TEST_CASE_MAX = 24,PATTERN_MAX = 10 };布尔_退出;字符 *_myArray[10]; };
【解决方案2】:

有一些方法可以解决这个问题: 一种方法是每次在类中显式写入静态成员:

class Base {/*...*/};

class InheritedFirst : public Base
{
    static constexpr const char* _myArray[10] = {"First"};
};

class InheritedSecond : public Base
{
    static constexpr const char* _myArray[10] = {"Second"};
};

另一种是从模板类中派生出当前类作为模板参数:

class Base {/*...*/};

template<typename T>
class GimmeArray
{
    static const char* _myArray[10];
};

class InheritedThird : public Base, public GimmeArray<InheritedThird>
{/*...*/};

class InheritedFourth : public Base, public GimmeArray<InheritedFourth>
{/*...*/};

template<typename T>
const char* GimmeArray<T>::_myArray[10] = {"Not specialized"};
template<>
const char* GimmeArray<InheritedThird>::_myArray[10] = {"Third"};
template<>
const char* GimmeArray<InheritedFourth>::_myArray[10] = {"Fourth"};

【讨论】:

  • 恕我直言,这对他来说太过分了。他应该只删除静态并将数组视为成员...
  • 我已经尝试过您的第一种方法。它给出了以下错误- constexpr 静态数据成员 '_myArray' 必须有一个初始化器仅供参考: Base.h [declared] static constexpr const char *_myArray[10]; Child1.CPP static constexpr const char static constexpr const char *Child1::_myArray[3] = {"red", "green", "blue"}; Child2.CPP static constexpr const char *Child1::_myArray[3] = {"black", "white", "brown"};我怎么了?
  • 你启用了 c++11 吗?如果否,则删除 = 及以上,并在类之外定义数组
  • 是的.. 我启用了 C++11.. 我已经在 CPP 文件中初始化了。
【解决方案3】:

静态变量可以被初始化一次。初始化静态成员时,您告诉编译器此静态变量位于哪个编译单元中。您已经在 Child1 中初始化了变量,您不能在 Child2 中进行初始化。

【讨论】:

    【解决方案4】:

    目标:

    提供一个单词数组,为每个派生类存储一次。同一类的所有实例应共享相同的单词数组。

    对共享数组的访问应该是多态的,因此观察者可以在不知道对象的确切类型的情况下访问该数组。

    在这种情况下,我将在基类上有一个非多态接口函数,它遵循多态实现。

    实现将为每个派生类定义一次,并提供对静态 const 单词数组的引用。

    作为静态常量,c++ 将保证它是在第一次使用时创建的。 c++11 将保证构造是原子的。

    类似这样的:

    #include <array>
    #include <iostream>
    #include <memory>
    
    using words_array = std::array<const char*, 3>;
    
    struct has_words_base
    {
    public:
        const words_array& get_words() const
        {
            return get_words_impl();
        }
    
    private:
        virtual const words_array& get_words_impl() const
        {
            static const words_array _ { "grey", "black", "brown" };
            return _;
        }
    
    };
    
    struct blue_words : has_words_base
    {
    private:
        virtual const words_array& get_words_impl() const override
        {
            static const words_array _ { "blue", "cyan", "indigo" };
            return _;
        }
    
    };
    
    struct red_words : has_words_base
    {
    private:
        virtual const words_array& get_words_impl() const override
        {
            static const words_array _ { "red", "vermillion", "scarlet" };
            return _;
        }
    };
    
    
    void test(const has_words_base& ob)
    {
        auto sep = "";
        for (auto&& w : ob.get_words()) {
            std::cout << sep << w;
            sep = ", ";
        }
        std::cout << std::endl;
    
    }
    
    int main()
    {
        test(*std::make_unique<has_words_base>());
        test(*std::make_unique<blue_words>());
        test(*std::make_unique<red_words>());
    
    }
    

    预期输出:

    grey, black, brown
    blue, cyan, indigo
    red, vermillion, scarlet
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-12
      • 1970-01-01
      • 2013-04-04
      • 2017-02-17
      相关资源
      最近更新 更多