访问头文件 C++ 中声明的向量(非全局)
Posted
技术标签:
【中文标题】访问头文件 C++ 中声明的向量(非全局)【英文标题】:Accessing vectors declared in header file C++ (not global) 【发布时间】:2021-12-28 13:29:04 【问题描述】:我提交了一个满足所有条件的作业,除了我不允许使用全局变量,除非它们是常量,并且我将我的向量设置为全局变量。
我现在发现在我的头文件以及我的类函数文件和我的主类文件中使用我的向量是不可能的。
我有一个主类和一个派生类,向量项属于派生类。现在,我已将矢量定义放在主要类的标题中:
vector<Stock> arrStock;
但是当尝试将对象从输入文件添加到向量中并随后对其执行操作时,我可以在 classes 函数类中设置函数,或者调用我在 main 中设置的函数类(如果我将函数设置为静态)。
我做错了什么?目前,按照代码的设置方式,我在主类中调用的所有函数都出现错误 E0245“非静态成员引用必须相对于特定对象”。可能值得注意的是,当我将向量设置为全局变量时,这些函数被定义为静态并且它们工作得很好,所以我对它们需要是静态的并且我的问题在于应用程序的事实持开放态度代替 Assignment2_classes.cpp 文件中的数组。
请看下面我的代码sn-ps:
作业2.h:
class Product
private:
string title, surname;
long long int isbn;
double wholesalePrice;
public:
string getTitle();
string getSurname();
long long int getIsbn();
double getWholesalePrice();
void setTitle(string);
void setSurname(string);
void setIsbn(long long int);
void setWholesalePrice(double);
Product();
~Product();
Product(string, string, long long int, double);
void importProducts();
void newProduct();
void delProduct();
void runReport();
void checkStock();
void clrStock();
vector<Stock> arrStock;
;
// creating the derived class Stock
class Stock :public Product
public:
double retailPrice;
char bookFormat;
int stockLevel;
double getRetailPrice();
char getBookFormat();
int getStockLevel();
void setRetailPrice(double);
void setBookFormat(char);
void setStockLevel(int);
Stock();
~Stock();
Stock(string, int, char, string, double, long long int, double);
void setStockInfo(long long int, string, string, double, int, double, char);
;
Assignment2_classes.cpp:
void Product::importProducts()
// code adapted from: https://***.com/questions/16878259/how-to-read-in-a-set-of-values-from-a-text-file-then-go-to-the-next-line-and-do
// telling the function which input file it is reading from
ifstream productsFile("products_v5.txt");
// creating local variables
Stock aStock;
double tempRetailPrice = 0;
string undsc = "_";
string space = " ";
size_t position;
std::cout << "Importing books...\n";
// reading the books into an array
while (productsFile >> aStock.title >> aStock.stockLevel >> aStock.bookFormat >> aStock.surname >> aStock.wholesalePrice >> aStock.isbn)
// replacing the underscores in the title names with spaces so the output looks better
// code adapted from https://www.educba.com/c-plus-plus-replace/
while ((position = aStock.title.find(undsc)) != string::npos)
aStock.title.replace(position, 1, space);
// calculating the retail prices of the books depending on their format
switch (aStock.bookFormat)
case 'a': tempRetailPrice = aStock.wholesalePrice * 1.43;
break;
case 'e': tempRetailPrice = aStock.wholesalePrice * 1.08;
break;
case 'h': tempRetailPrice = aStock.wholesalePrice * 1.45;
break;
case 's': tempRetailPrice = aStock.wholesalePrice * 1.27;
break;
aStock.setRetailPrice(tempRetailPrice);
arrStock.push_back(aStock);
// letting the user know how many books have been added and how many books are currently in the array
std::cout << "\n" << to_string(arrStock.size()) << " books have been added.\n";
std::cout << "\nBiblioden Books currently has " << to_string(arrStock.size()) << " different books.\n";
Assignment2_main.cpp:
int main()
char createBook;
char deleteBook;
char viewReport;
char checkOrders;
// creating the heading of the output
cout << "-----------------------------------------------------------------------------------------\n" << " Biblioden Systems\n" << "-----------------------------------------------------------------------------------------\n";
ifstream productsFile("products_v5.txt");
// checking whether the file is open and gracefully exiting if it can't be opened
if (!productsFile.is_open())
cout << "\nCannot open file.\n";
return 1;
Product::importProducts();
//closing the file
productsFile.close();
cout << "\nWould you like to enter a new book? (Y/N): ";
cin >> createBook;
if (createBook == 'Y' || createBook == 'y')
Product::newProduct();
cout << "\nWould you like to delete a book? (Y/N) ";
cin >> deleteBook;
if (deleteBook == 'Y' || deleteBook == 'y')
Product::delProduct();
cout << "\nWould you like to view a report? (Y/N) ";
cin >> viewReport;
if (viewReport == 'Y' || viewReport == 'y')
ofstream report("report.txt");
// checking whether the file is open and gracefully exiting if it can't be opened
if (!report.is_open())
cout << "\nCannot open file.\n";
return 1;
else
Product::runReport();
// closing the file
report.close();
cout << "\nWould you like to check the order list against the stock list? (Y/N) ";
cin >> checkOrders;
if (checkOrders == 'Y' || checkOrders == 'y')
ifstream ordersFile("orders_v5.txt");
// checking whether the file is open and gracefully exiting if it can't be opened
if (!ordersFile.is_open())
cout << "\nCannot open file.\n";
return 1;
else
Product::checkStock();
// closing the file
ordersFile.close();
// clearing out the array once the user is finished with it
Product::clrStock();
return 0;
【问题讨论】:
调用MyClass::myFunc();
要求myFunc()
是static
的MyClass
成员,这里不是这种情况。
嗨@Fareanor,我知道这是问题所在,但我该如何解决呢?函数是否应该是 static ,如果是这样,我如何使用向量修复 Assignment2_classes.cpp 文件中抛出的错误(相同的 E0245 错误刚刚应用于函数中的向量调用)?或者它们不应该是静态的,如果是,我该如何修复 Assignment2_main.cpp 文件中的错误?
当然不是,我想你会感兴趣阅读一本好的 C++ 书籍以更好地理解 static
的作用。在您的情况下,您需要一个适当的类实例来处理(请参阅我的答案)。
除非您希望类的所有可能实例共享相同的唯一成员(或者如果您根本不想要一个实例,因此不需要一个唯一向量等......),那么您可以你所有的成员static
,它应该可以工作。
@Fareanor,我确实认为我希望所有可能的向量实例共享相同的唯一成员......但是你在句子的前半部分提到的是什么?
【参考方案1】:
如 cmets 中所述,调用 Product::importProducts();
要求 importProducts()
是 Product
的 static
成员函数。
在您的情况下,您不能将其声明为 static
(这样做没有意义),因为您在函数内部使用(非静态)类成员。
您需要一个Product
的实例来调用成员函数。
例如:
Product p; // Create an instance of Product
p.importProducts(); // Call importProducts() from (and for) the previously created instance
另一方面,如果您不想创建Product
的任何实例,因此您想要整个程序的唯一向量,您可以标记您的成员(和成员函数)static
来解决您的问题问题。
【讨论】:
哦,这确实有道理。但是我刚刚重新构建了程序,显然仍有 67 个错误出现,其中至少有一些与您和 vegalock 在下面讨论的基类的声明有关。我有一个巨大的问题围绕着我应该在哪里声明我的向量,因为它的对象是派生类而不是基类的成员。我在我的教科书中找不到任何这种性质的东西。 @crab_attack 如果你想改成static
,我做了一个编辑(即你不需要实例)
@crab_attack 关于基类持有派生实例的问题,你需要了解多态是如何工作的,这是你需要的。
嘿@Fareanor 我没有运气弄清楚多态性是如何工作的,我见过的所有示例都在主类中声明了向量,这对我不起作用,因为我参考在我的类函数文件中。整个情况似乎很荒谬,我已经为此工作了 5 个小时以阻止变量成为全局变量,当它完美地工作并且它是全局的时,是否有我遗漏的东西?看起来它应该比每次更改任何内容时都会引发数百个错误更简单
@crab_attack 您需要阅读有关 C++ 多态性的课程,因为它是一个庞大的主题。我已经为您的用例编写了一个使用多态性的最小示例:You can see it here【参考方案2】:
成员变量arrStock
的声明在Stock 类声明之前。您不能引用尚未声明的类。您必须将向量设为指针向量(或 shared_ptr),然后您可以在声明 Product 之前转发声明该类:
class Stock;
【讨论】:
不错,但我认为拥有一个需要知道其自身特定派生的基类是一个糟糕的设计。 OP 应该更好地依赖多态性,它就是为此而生的。 我不会争论这一点,也不推荐成员变量是公共的这一事实。以上是关于访问头文件 C++ 中声明的向量(非全局)的主要内容,如果未能解决你的问题,请参考以下文章