无法将多维数组传递给g中的基类++ 我是C++新手,但在C中有很多年,所以如果你看到C风格的代码,我想掌握指针、解引用、句柄、引用、数组参数的概念,我仍然有困难。

无法将多维数组传递给g中的基类++ 我是C++新手,但在C中有很多年,所以如果你看到C风格的代码,我想掌握指针、解引用、句柄、引用、数组参数的概念,我仍然有困难。,c++,multidimensional-array,arduino,g++,C++,Multidimensional Array,Arduino,G++,以下是使用g++11 arduino编译的atmel微控制器 我试图将无符号int的二维固定大小数组作为基类构造函数的参数传递,但无论我如何尝试,我都无法让它传递基类中的数组内容。这里是原始代码,没有包含,只有基本代码 在本例中,将调用派生构造函数,我希望它调用DisplayDriver构造函数并将_colorTable数组作为参数传递给它: DisplayDriver.hpp 1.hpp 导出的.cpp DisplayDriver.cpp 我为数组尝试了许多不同的参数类型: 无符号整数*颜色表

以下是使用g++11 arduino编译的atmel微控制器

我试图将无符号int的二维固定大小数组作为基类构造函数的参数传递,但无论我如何尝试,我都无法让它传递基类中的数组内容。这里是原始代码,没有包含,只有基本代码

在本例中,将调用派生构造函数,我希望它调用DisplayDriver构造函数并将_colorTable数组作为参数传递给它:

DisplayDriver.hpp

1.hpp

导出的.cpp

DisplayDriver.cpp

我为数组尝试了许多不同的参数类型:

无符号整数*颜色表[18][2] 无符号整数颜色表[][2] 无符号整型和彩色表[18][2] 有或没有常数
问题与正确的类型无关。问题是您正在DisplayDriver的构造函数中使用派生的数据成员。调用DisplayDriver构造函数时,派生对象尚未构造,因此值是垃圾

简单的解决方法是使_可着色静态


问题与正确的类型无关。问题是您正在DisplayDriver的构造函数中使用派生的数据成员。调用DisplayDriver构造函数时,派生对象尚未构造,因此值是垃圾

简单的解决方法是使_可着色静态


这里的问题是初始化的顺序:

派生实例

扩展到:

调用构造函数派生::派生 要构造派生类,必须首先构造基类。所以 DisplayDriverxResolution、yResolution、\u colorTable正在运行。 所有成员变量都是按照其构造函数在类中声明的顺序构造的。在本例中,您指定了该实例。_colorTable被初始化为该数组。 已执行派生::派生的主体。 所以,在第二节。您正在使用未初始化的变量,该变量是未定义的行为- 它可以包含任何内容。在本例中,变量包含零数组

要解决此问题,可以将_colorTable标记为static


也不需要对int使用const,因为它是通过值传递的。

这里的问题是初始化的顺序:

派生实例

扩展到:

调用构造函数派生::派生 要构造派生类,必须首先构造基类。所以 DisplayDriverxResolution、yResolution、\u colorTable正在运行。 所有成员变量都是按照其构造函数在类中声明的顺序构造的。在本例中,您指定了该实例。_colorTable被初始化为该数组。 已执行派生::派生的主体。 所以,在第二节。您正在使用未初始化的变量,该变量是未定义的行为- 它可以包含任何内容。在本例中,变量包含零数组

要解决此问题,可以将_colorTable标记为static


另外,不需要对int使用const,因为它是通过值传递的。

正如其他人所说,您的问题是在初始化之前使用了_colorTable。如果您不介意所有派生实例共享一个公共的_colorTable,这就是类声明上下文中静态的含义,那么使_colorTable静态工作

但是,如果您希望每个实例都有自己的_colorTable,那么解决问题的一种方法就是使用。这个习惯用法使用基类的初始化顺序。当一个类有多个基类时…:

class A {  };
class B {  };
class C {  };

class D : public A, public C, public virtual B {  }; // note virtual

…C++表示初始化顺序为:

所有虚拟基类的声明顺序为左至右 对

所有非虚拟基类的声明顺序为左至右 对

如果你创建了一个D实例,那么D的基类就按照下面的顺序初始化:第一个B,然后是A,然后C。如果你刚开始,也许更多,如果你在C++上使用C++,那么你就不必担心虚拟基类。p> 因此,在您的例子中,利用您对基类初始化顺序的了解,您可以使用“来自成员的基类”习惯用法。创建一个新类并将_colorTable从派生类移动到新类:

// Derived.hpp

// namespace detail {

class DerivedDMembers 
{
protected:
  const unsigned int _colorTable[18][2] =
  {
    {4, 2},
    {9, 31},
    ... // 16 other lines.
  };
};

// } // namespace detail

// if you feel that DerivedDMembers is polluting your namespace
// you can put it in a namespace called "detail". there's nothing
// special about 'detail' other than that "internal details" by
// convention are put in it.    
已从您的新类派生成员:

现在,您可以安全地将_colorTable传递给基类DisplayDriver:

您不必在派生的构造函数初始化器列表中显式调用DerivedMembers的默认构造函数,因为如果省略基类构造函数调用,则会隐式调用其默认构造函数

现在,派生的每个实例都有自己的_colorTable,您可以使用_
用于初始化DisplayDriver的colorTable

正如其他人所说,您的问题在于您在初始化之前使用了_colorTable。如果您不介意所有派生实例共享一个公共的_colorTable,这就是类声明上下文中静态的含义,那么使_colorTable静态工作

但是,如果您希望每个实例都有自己的_colorTable,那么解决问题的一种方法就是使用。这个习惯用法使用基类的初始化顺序。当一个类有多个基类时…:

class A {  };
class B {  };
class C {  };

class D : public A, public C, public virtual B {  }; // note virtual

…C++表示初始化顺序为:

所有虚拟基类的声明顺序为左至右 对

所有非虚拟基类的声明顺序为左至右 对

如果你创建了一个D实例,那么D的基类就按照下面的顺序初始化:第一个B,然后是A,然后C。如果你刚开始,也许更多,如果你在C++上使用C++,那么你就不必担心虚拟基类。p> 因此,在您的例子中,利用您对基类初始化顺序的了解,您可以使用“来自成员的基类”习惯用法。创建一个新类并将_colorTable从派生类移动到新类:

// Derived.hpp

// namespace detail {

class DerivedDMembers 
{
protected:
  const unsigned int _colorTable[18][2] =
  {
    {4, 2},
    {9, 31},
    ... // 16 other lines.
  };
};

// } // namespace detail

// if you feel that DerivedDMembers is polluting your namespace
// you can put it in a namespace called "detail". there's nothing
// special about 'detail' other than that "internal details" by
// convention are put in it.    
已从您的新类派生成员:

现在,您可以安全地将_colorTable传递给基类DisplayDriver:

您不必在派生的构造函数初始化器列表中显式调用DerivedMembers的默认构造函数,因为如果省略基类构造函数调用,则会隐式调用其默认构造函数


现在,派生的每个实例都有自己的_colorTable,您可以使用_colorTable初始化DisplayDriver

使用二维std::vector或std::array会更简单。arduino中没有这样的东西。除非以牺牲宝贵的记忆为代价。只有在没有其他方法的情况下,我才实现自己的标准库。使用二维std::vector或std::array会更简单。arduino中没有这样的东西。除非以牺牲宝贵的记忆为代价。只有在没有其他方法的情况下,我才能实现自己的标准库。我认为派生的hpp文件中的_colorTable在调用base的构造函数之前已经初始化。换句话说,我认为派生构造函数将在callindbase之前完成。通过将其设置为静态,_colorTable将在所有这些之前初始化。谢谢。如果我将其设置为静态,我会将一条消息翻译为“const unsigned int_colorTable[18][2]”类型的成员不能有类初始值设定项。我现在就去找。不容易…@sbeaudoin您需要将声明与定义分开,请参阅我发布的代码。@sbeaudoin声明放在您的头文件中,但初始化值的定义必须放在cpp文件中。是的,我就是这么做的,它工作得很好。我必须记住,hpp文件不是编译的文件,它与C世界中的分部类不同。我是这么想的,我明白。我认为派生的hpp文件中的_colorTable在调用base的构造函数之前已经初始化。换句话说,我认为派生构造函数将在callindbase之前完成。通过将其设置为静态,_colorTable将在所有这些之前初始化。谢谢。如果我将其设置为静态,我会将一条消息翻译为“const unsigned int_colorTable[18][2]”类型的成员不能有类初始值设定项。我现在就去找。不容易…@sbeaudoin您需要将声明与定义分开,请参阅我发布的代码。@sbeaudoin声明放在您的头文件中,但初始化值的定义必须放在cpp文件中。是的,我就是这么做的,它工作得很好。我必须记住,hpp文件不是编译的文件,它与C世界中的分部类不同。这是我首先想到的。关于const,我还没有真正理解它的所有味道,所以我把它放在任何我能放的地方,直到它不起作用…@sbeaudoin是的,它一开始可能不是直观的,尤其是在更复杂的情况下,有指针之类的。特别是在C背景下,但它是非常有用的特性。关于您的函数:int是通过value=通过copy传递的,因此函数不能更改传递给函数的变量。它唯一能做的就是你不能改变新的临时变量/参数的值,它将在函数结束时被销毁。关于const,我还没有真正理解它的所有味道,所以我把它放在任何地方,直到它不起作用为止…@sbeaudoin Yes,起初它可能不是直观的,尤其是在更复杂的情况下,有指针之类的。特别是在C背景下,但它是非常有用的特性。关于您的函数:int是通过value=通过copy传递的,因此函数不能更改传递给函数的变量。它所做的唯一一件事是您不能更改
新的临时变量/参数将在函数结束时销毁。感谢您提供的精度和解释其他路径。但将只有一个显示器附加,所以只有一个颜色表。我会记住你写的东西,以备以后需要。没问题。关于代码的另一件事与您的问题无关:在DisplayDriver的构造函数中,您使用const unsigned int colorTable[18][2]。使用该签名,它将接受任何大小为[n][2]的数组,其大小为n>0。如果您只需要大小为[18][2]的数组,那么一个解决方案是使用常量unsigned&colorTable[18][2];对数组的引用。阅读更多。另外,unsigned类型与unsigned int类型相同。真的吗?编译器不会检查数组大小吗?If将遵循您关于使用参数引用的建议。谢谢。谢谢你的精确和解释另一条路线。但将只有一个显示器附加,所以只有一个颜色表。我会记住你写的东西,以备以后需要。没问题。关于代码的另一件事与您的问题无关:在DisplayDriver的构造函数中,您使用const unsigned int colorTable[18][2]。使用该签名,它将接受任何大小为[n][2]的数组,其大小为n>0。如果您只需要大小为[18][2]的数组,那么一个解决方案是使用常量unsigned&colorTable[18][2];对数组的引用。阅读更多。另外,unsigned类型与unsigned int类型相同。真的吗?编译器不会检查数组大小吗?If将遵循您关于使用参数引用的建议。谢谢
class Derived : public DisplayDriver
{
public:
    Derived(const int xResolution, const int yResolution);

private:
    static const unsigned int _colorTable[18][2];
};
const unsigned int Derived::_colorTable[18][2] =
{
    {4, 2},
    {9, 31},
    ...
};
class A {  };
class B {  };
class C {  };

class D : public A, public C, public virtual B {  }; // note virtual
// Derived.hpp

// namespace detail {

class DerivedDMembers 
{
protected:
  const unsigned int _colorTable[18][2] =
  {
    {4, 2},
    {9, 31},
    ... // 16 other lines.
  };
};

// } // namespace detail

// if you feel that DerivedDMembers is polluting your namespace
// you can put it in a namespace called "detail". there's nothing
// special about 'detail' other than that "internal details" by
// convention are put in it.    
// Derived.hpp

// note how DerivedDMembers is listed before DisplayDriver, which
// is crucial
class Derived : protected DerivedDMembers, public DisplayDriver
{
public:
  Derived(const int xResolution, const int yResolution);

  // note, _colorTable is now in DerivedDMembers  
};
// Derived.cpp

Derived(const int xResolution, const int yResolution) : DisplayDriver(xResolution, yResolution, _colorTable) {  }