C++将const char*指针数组传递给对象

4

亲爱的StackOverFlowers,

我在将const char* []传递给对象时遇到了问题。情况如下。

我有一个名为UlamScreen的类,其中包含几个字符串的const char* [] UlamScreen 还包含一个名为homeScreenMenu的对象。

class UlamScreen {
  const char* homeScreenText[5] = {"EVA dun", "Sabine", "TPU dun", "test Wout", 
  UlamScreenMenu homeScreenMenu;
};

class UlamScreenMenu {    
private:
  const char* _menuText[];

public:
  UlamScreenMenu(const char*[]);
  void drawMenu();
};

我希望将const char* []传递给,以便我可以在名为void drawMenu的成员函数中使用它,如下所示:

void UlamScreenMenu::drawMenu() {
  for (int i = 0; i < menuItems; i++) {
      tft.println(_menuText[i]);
  }
}

我将它传递给 UlamScreenMenu 的构造函数,方法如下:

UlamScreen::UlamScreen() : homeScreenMenu(homeScreenText) {

}

UlamScreenMenu::UlamScreenMenu(const char* menuText[], int length) {
  for(int i = 0; i < length; i++) {
    _menuText[i] = menuText[i];
  }
}

我原以为这样做可以起作用,但由于某种原因,它没有起到作用。在使用void drawMenu时,tft.println(_menuText[i]);不能将任何内容发送到我的tft屏幕上。当我从UlamScreen类中使用tft.println(_menuText[i]);时,它完美地工作。
需要明确的是,我可以在UlamScreenMenu类中使用tft对象,因为其他函数如tft.drawRect()正常工作。
这种传递const char* []的方式有什么问题吗?谢谢。

9
为什么您不使用标准库类型,如std::stringstd::vector?此外,const char* _menuText[];不是标准C++的有效声明。 - UnholySheep
1
作为 std::vector 的替代方案,请参阅 std::array - Some programmer dude
1
传递 std::arraystd::vector 而不是 C 风格数组。 - Jesper Juhl
1个回答

3
在C++中,您不能声明类型为const char* x[]的成员变量,因为这将表示一个灵活数组成员。灵活数组成员是C特性,允许结构体的最后一个成员是大小可变的数组(例如,未知大小/灵活数组成员的数组)。然而,在函数中使用类型为const char* x[]的参数是被支持的,并且基本上具有与const char** x相同的含义。
如果您坚持要使用类型为const char**的成员,那么您必须在该类中处理内存管理。这意味着:要小心地分配、释放、复制、移动、复制赋值和移动赋值该类的对象(例如,0/3/5规则)。
如果您像评论中建议的那样使用标准库集合,例如std::vector,这些类将以可靠的方式为您完成所有这些工作。请参见下面的示例,说明两者之间的差异:
请注意,C++版本可能甚至不会接受const char*[]参数,而直接采用const std::vector<const char*> &x参数。但我保留了构造函数中的const char*[]参数,以在两个变量中提供相同的接口。
// Variant 1: "old" C-style:
class Menu {
public:

    Menu(const char* x[], int length) {
        m_x = new const char*[length];
        m_length = length;
        for (int i=0; i<length; i++) {
            m_x[i] = x[i];
        }
    }

    ~Menu() {
        delete[] m_x;
    }

    // TODO: implement copy- and move constructors + copy- and move assignments
    // ...

    void print() {
        for (int i=0; i<m_length; i++) {
            std::cout << m_x[i] << std::endl;
        }
    }

private:
    const char** m_x = nullptr;
    int m_length;
};

#include <vector>

// Variant 2: a C++- way:
class Menu2 {
public:
    Menu2(const char* x[], int length) {
        m_x.assign(x, x+length);
    }

    void print() {
        for (auto s : m_x) {
            std::cout << s << std::endl;
        }
    }

    // Menu2 does not manage memory on its own, hence:
    // No special copy/move - constructors/assignments to be implemented.
    // No special destructor necessary
private:

    std::vector<const char*> m_x;
};

int main() {
    const char* x1[3] = {"one","two","three" };
    const char* x2[2] = {"eins","zwei" };

    // Variant 1
    Menu m1(x1, 3);
    m1.print();

    // Variant 2
    Menu2 m2(x2, 2);
    m2.print();
}

1
非常感谢您详细的回答,它非常有效!我使用了std::vector。 - Daan van Driel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接