无法将多维数组传递给g中的基类++ 我是C++新手,但在C中有很多年,所以如果你看到C风格的代码,我想掌握指针、解引用、句柄、引用、数组参数的概念,我仍然有困难。
以下是使用g++11 arduino编译的atmel微控制器 我试图将无符号int的二维固定大小数组作为基类构造函数的参数传递,但无论我如何尝试,我都无法让它传递基类中的数组内容。这里是原始代码,没有包含,只有基本代码 在本例中,将调用派生构造函数,我希望它调用DisplayDriver构造函数并将_colorTable数组作为参数传递给它: DisplayDriver.hpp 1.hpp 导出的.cpp DisplayDriver.cpp 我为数组尝试了许多不同的参数类型: 无符号整数*颜色表[18][2] 无符号整数颜色表[][2] 无符号整型和彩色表[18][2] 有或没有常数无法将多维数组传递给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 我为数组尝试了许多不同的参数类型: 无符号整数*颜色表
问题与正确的类型无关。问题是您正在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) { }