【问题标题】:How to initialize static const member that is array of another class, and use it?如何初始化另一个类的数组的静态常量成员,并使用它?
【发布时间】:2019-10-02 00:54:09
【问题描述】:

我正在尝试使用库存实例化自动售货机。我计划的库存是一系列类饮料。这是我到目前为止所写的内容。

VendingMachine.h - 应该包含 Drinks 类的数组

#include "Drinks.h"

class VendingMachine {
   private:
      static const int NUM_DRINKS = 5;
      static const Drinks drinks[NUM_DRINKS];
   public:
      VendingMachine();
};

Now Drinks.h

#include <string>

class Drinks {
   private:
      std::string name;
      double price;
      int qtyInMachine;
   public:
      Drinks(std::string name, double price, int qtyInMachine);
      void decrementQuantity();
};

VendingMachine.cpp

#include "VendingMachine.h"

VendingMachine::VendingMachine() {
}

Drinks.cpp

#include <string>
#include "Drinks.h"

Drinks::Drinks(std::string n, double p, int qty) : name(n), price(p), qtyInMachine(qty) {
}
void Drinks::decrementQuantity() {
   qtyInMachine--;
}

现在是测试程序

#include <iostream>
#include "VendingMachine.h"

const Drinks VendingMachine::drinks[VendingMachine::NUM_DRINKS] {Drinks("Cola",1.25,20),
      Drinks("Root Beer",1.35,20),Drinks("Orange Soda",1.20,20),Drinks("Grape Soda",1.20,20),
      Drinks("Bottled Water",1.55,20)};

int main() {
   VendingMachine vm1;
   for (int i = 0; i < VendingMachine::NUM_DRINKS; i++) {
      std::cout << vm1.drinks[i].name << " ";
   }
}

我定义饮料编译器的行抱怨它不是一个完整的 const 表达式,并且 VendingMachine::NUM_DRINKS 在上下文中是私有的。它为我的带有 NUM_DRINKS 的 for 语句声明了相同的私有上下文错误,在我的 cout 声明中它声称对于饮料和名称都相同。我需要知道如何以及在何处初始化饮料以及如何在 main 中使用而不会出现“在此上下文中为私有”错误。

由于我是一般的课程和 OO 的极端初学者,我找不到我的错误。非常感谢任何帮助。

【问题讨论】:

  • 你想要constexpr;或者只是在程序开始时手动初始化它们。
  • 喜欢一开始就初始化,但我会用我目前写的最简单的解决方案

标签: c++ arrays static-initialization datamember


【解决方案1】:

实际上,您需要研究/修改封装和数据隐藏的 OOP 概念以及访问说明符(privatepublic)的 C++ 特定功能,以及它们的使用方式和上下文。

注意:还有一个protected 访问说明符,您可以在继承主题中研究它。

  • public 类的一部分对外界可见,例如其他类、函数等。
  • private 只能在类本身内访问。

您在 public 上下文中访问了私有成员,这就是您收到这些错误的原因,即:

class VendingMachine {
   private:
      static const int NUM_DRINKS = 5;          // private to class
      static const Drinks drinks[NUM_DRINKS];   // private to class
   public:
      VendingMachine(){}
};

并且,在main 函数中:

int main() {
   VendingMachine vm1;
   for (int i = 0; i < VendingMachine::NUM_DRINKS; i++) { // accessing private member VendingMachine::NUM_DRINKS
      std::cout << vm1.drinks[i].name << " ";             // accessing private members vm1.drinks[i].name
   }
}

name 数据成员是 Drinks 类的 private,您在 main 中公开访问它。

这些是您需要解决的问题。

为了访问私有数据成员,通常使用访问器函数,例如访问name,您将有一个公共getName() 方法等等。

  • 要访问私有实例数据成员,您需要公共方法。
  • 要访问privatestatic数据成员或类成员,您需要publicstatic成员函数。

我想指出的另一件事是:

// Declaration: Observe names of the method arguments
Drinks(std::string name, double price, int qtyInMachine); 

// Definition: Observe the names of the arguments here 
Drinks::Drinks(std::string n, double p, int qty) : name(n), price(p), qtyInMachine(qty) {
}

在像现在这样的单独接口/实现场景中,这并不重要。但是,如果您稍后需要在类中移动定义,那么您必须使它们保持一致。因此,从长远来看,这是一种维护开销。


这是一个经过最小修改的工作示例:http://ideone.com/tr5oZu

【讨论】:

  • 谢谢。但是问题是,为什么 VendingMachine::NUM_DRINKS 在我的饮料数组的定义中起作用,但它需要在打印 for 循环中使用 get 函数?
  • @WilliamS:因为,当您初始化作为类的一部分的数组时,它在那里可见 - 两者都是私有成员。静态数据成员需要在源文件中初始化。但是,在您使用的主要功能中,这意味着它正在public 上下文中使用,这就是您需要public getter 方法来访问它的原因。
  • @WilliamS:初始化通常在相应的源文件中完成,即在您的情况下是 Drinks.cpp。在main.cpp中初始化,也是违反OOP的信息隐藏原则。应该使用 setter 类函数来完成。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-18
  • 2020-04-25
  • 1970-01-01
  • 2012-02-18
  • 1970-01-01
相关资源
最近更新 更多