繁体   English   中英

向前声明并动态分配该声明类的指针数组?

[英]Forward Declaring and Dynamically Allocating an Array of Pointers of that Declared Class?

我的C ++实验室整天都遇到这个问题。 据我所知,除了我的教授在我们的作业中规定的这一条款外,我正在做所有的工作:

源文件中类声明的顺序是InventorySystem,InventoryItem,Product和eProduct。 由于InventorySystem包含InventoryItem指针数组,因此必须对InventoryItem使用前向声明

因此,InventoryItem->产品-> eProduct在派生的层次结构中相互关联,我们的任务是将这种层次结构与InventorySystem类结合使用,以管理指向eProduct对象的指针数组。

不幸的是,我对StackOverflow帖子的所有讨论都使我得出这样的结论:对我的要求是不可能的。 据我了解,前向声明“实际上只是告诉编译器该类存在,这才有用”,任何与代码的结构或定义有关的上下文都不能与前向声明一起使用-似乎与其他声明直接冲突我实验室的要求,因为InventorySystem有一个称为BuildInventory的方法,该方法可解析格式化的文本文件并动态分配指向eProduct对象的指针数组。 那不需要“转发声明的”对象的构造函数吗?

我真的,真的希望我只是C ++的新手,我被误导了,因为这个问题整日使我发疯。

在此先感谢您的帮助。

PS:对于函数名和变量的奇怪字形,我们感到抱歉,这是我的教授在我们的作业中写该大小写的方式,我认为更安全地使用他所建立的内容。

//Format for text file is Name;Quantity;Price;Condition
void BuildInventory()
{
    ifstream fin ("in.txt");

    string     name="";
    string     Buffer = "";
    int        quantity = 0;
    double     price = 0.0;
    int        temp = 0; 
    if (!fin) {
        cout << "ERROR: Failed to open input file\n";
        exit(-1);
    }

    while ( getline (fin, Buffer, ';') ) {
        string      condChar = "";
        Condition   condition = NEW;

        name = Buffer;
        getline (fin, Buffer, ';');
        quantity = atol (Buffer.c_str ( ) );   
        getline (fin, Buffer, ';');
        price = atof (Buffer.c_str( ) );  
        getline (fin, Buffer, '\n') ; 
        condChar = Buffer.c_str();

        if(condChar.compare("R") == 0)
            condition = REFURBISHED;
        else if(condChar.compare("U") == 0)
            condition = USED;
        else if(condChar.compare("D") == 0)
            condition = DEFECTIVE;

        ep = new eProduct(name, quantity,  price , condition);
        ItemList[ItemCount] =ep;
        ++ItemCount;

        fin.ignore(1, '\n');
    }
    fin.close();
    Sort();
}

以下是InventorySystem动态分配的指针数组必须指向的对象层次结构的构造函数(所有指向eProducts)

//Constructor of eProduct
eProduct(string Name, int Quantity, double Price, Condition condition)
    :Product(Name, Quantity, Price)
{
    this -> condition = condition;
}
//Constructor of Product
Product():ProductID(0), Price(0.0){}
Product(string Name, int Quantity, double Price)
    :InventoryItem(Name, Quantity)
{
    this -> Price = Price;
    this -> ProductID = generateProductID();
}
//Constructor of InventoryItem
InventoryItem(std::string Name, int Quantity)
{
    this -> Name = Name;
    this -> Quantity = Quantity;
}

秘诀在于您的教授给您的指示以及您自己的描述中:

源文件中类声明的顺序是InventorySystem,InventoryItem,Product和eProduct。 由于InventorySystem包含InventoryItem指针数组,因此必须对InventoryItem使用前向声明

我们的任务是将继承关系与InventorySystem类结合使用,以管理指向 eProduct对象的指针数组

所以你需要这样的东西:

class InventoryItem; // forward declaration

class InventorySystem
{
    ...
    InventoryItem* ItemList[TheArraySizeHere]; // array of InventoryItem pointers
    ...
};

class InventoryItem
{
    ...
};

class Product : public InventoryItem
{
    ...
};

class eProduct : public Product
{
    ...
};

由于eProduct源自InventoryItem ,因此您可以将eProduct指针存储在InventoryItem指针的数组中。

这是另一个难题。 由于尚未声明eProduct类,因此无法在InventorySystem类声明中内联实现BuildInventory() 在定义eProduct之后,需要分离并实现BuildInventory()实现,例如:

class InventoryItem; // forward declaration

class InventorySystem
{
    ...
    InventoryItem* ItemList[TheArraySizeHere]; // array of InventoryItem pointers
    ...
    void BuildInventory();
};

class InventoryItem
{
    ...
};

class Product : public InventoryItem
{
    ...
};

class eProduct : public Product
{
    ...
};

...

void InventorySystem::BuildInventory()
{
    // implementation here ...
}

通常,这是通过将所有声明放置在.h文件中,并将所有实现放置在#include.h文件的.c / .cpp文件中来完成的,例如:

Inventory.h:

#ifndef InventoryH
#define InventoryH

class InventoryItem; // forward declaration

class InventorySystem
{
    ...
    InventoryItem* ItemList[TheArraySizeHere]; // array of InventoryItem pointers
    ...
};

class InventoryItem
{
    ...
    InventoryItem(std::string Name, int Quantity);
    ...
};

class Product : public InventoryItem
{
    ...
    Product();
    Product(string Name, int Quantity, double Price);
    ...
};

class eProduct : public Product
{
    ...
    eProduct(string Name, int Quantity, double Price, Condition condition);
    ...
};

#endif

Inventory.cpp:

#include "Inventory.h"

//Constructor of InventoryItem
InventoryItem::InventoryItem(std::string Name, int Quantity)
{
    this->Name = Name;
    this->Quantity = Quantity;
}

//Constructor of Product
Product::Product() : ProductID(0), Price(0.0) {}
Product::Product(string Name, int Quantity, double Price)
    : InventoryItem(Name, Quantity)
{
    this->Price = Price;
    this->ProductID = generateProductID();
}

//Constructor of eProduct
eProduct::eProduct(string Name, int Quantity, double Price, Condition condition)
    : Product(Name, Quantity, Price)
{
    this->condition = condition;
}

void InventorySystem::BuildInventory()
{
    // implementation here ...
}

InventorySystem具有一个称为BuildInventory的必需方法,该方法可解析格式化的文本文件并动态分配指向eProduct对象的指针数组。 那不需要“转发声明的”对象的构造函数吗?

回答

是的,这将需要eProduct的完整类定义以及从InventoryItem派生的任何其他叶级别类。 但是,这是在类的实现中。

该类的定义仍然可以继续使用指向转发的声明类的指针。

前向声明允许您指定前向声明类型的指针和引用,还可以在函数声明(返回类型和参数类型)中使用该类型。 的确,向前声明不允许你真正实例的类型,例如,作为一个局部变量或类的属性,因为它不是一个完整的类型,但(这就是所谓的不完全类型 ),但前提是这不是什么是必需的,您应该能够使其正常运行。

如果您需要在函数体内使用类型的实例化,那也可以做到,只要您在完全定义了依赖类型之后定义实际的函数体即可。 通常通过将类定义和函数实现分成两个单独的源文件(标头( .h.hpp )和代码( .c.cpp ))来完成。 在实际进入代码之前,代码文件需要包括它们所依赖的所有标头。

请参阅何时可以使用前向声明? 很好地总结了可以使用和不能使用前向声明的内容。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM