简体   繁体   中英

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

I have been having this problem all day with my C++ lab. As far as I can tell, I have everything working, except for this one clause that my professor has stipulated in our assignment:

The order of class declarations in your source file is InventorySystem, InventoryItem, Product, eProduct. Since InventorySystem contains InventoryItem array of pointers you must use forward declaration on InventoryItem

So InventoryItem -> Product -> eProduct relate to each other in a derived heriarchy, and our assignment is to write that heirarchy combined with an InventorySystem class to manage an array of pointers to eProduct objects.

Unfortunately, all of my trolling of StackOverflow posts have led me to the conclusion that what is asked of me is impossible. As I understand forward declaration, "it is really only useful to inform the complier that the class exists" and anything contextual concerning the structure or the definition of the code would not work with forward declaration-- something that seems to directly conflict with the other requirements of my lab, as InventorySystem has a method required called BuildInventory that parses a formatted textfile and dynamically allocates an array of pointers to eProduct objects. Does that not require a constructor of the "forward declared" object?

I really, really hope that I'm just being a newbie at C++ and that I'm massively misinformed, since this issue has been driving me nuts all day.

Thanks in advance for your help.

PS: sorry for the weird casing of function names and variable, it is how my professor wrote the casing in the our assignment, and I thought it safer just to roll with what he established rather.

//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();
}

Below are the constructors for the hierarchy of objects that the array of pointers dynamically allocated by InventorySystem have to point to (all point to 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;
}

The secret is in the instructions your professor gave you, as well as in your own description:

The order of class declarations in your source file is InventorySystem, InventoryItem, Product, eProduct. Since InventorySystem contains InventoryItem array of pointers you must use forward declaration on InventoryItem

our assignment is to write that heirarchy combined with an InventorySystem class to manage an array of pointers to eProduct objects.

So you need something like this:

class InventoryItem; // forward declaration

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

class InventoryItem
{
    ...
};

class Product : public InventoryItem
{
    ...
};

class eProduct : public Product
{
    ...
};

Since eProduct derives from InventoryItem , you can store eProduct pointers in the array of InventoryItem pointers.

Here is the other piece of the puzzle. You cannot implement BuildInventory() inline inside the InventorySystem class declaration, since the eProduct class has not been declared yet. The implementation of BuildInventory() needs to be separated and implemented after eProduct is defined, eg:

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 ...
}

This is typically done by place all of the declarations in a .h file, and all of the implementations in a .c / .cpp file that #include s the .h file, eg:

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 ...
}

Question

InventorySystem has a method required called BuildInventory that parses a formatted textfile and dynamically allocates an array of pointers to eProduct objects. Does that not require a constructor of the "forward declared" object?

Answer

Yes, that would require the full class definition of eProduct and any other leaf level classes derived from InventoryItem . However, that is in the implementation of the class.

The definition of the class can still continue to use pointers to the forwarded declared classes.

A forward-declaration allows you to specify pointers and references of the forward-declared type, and also use the type in function declarations (in the return type and parameter types). It is true that a forward-declaration does not allow you to actually instantiate the type, eg as a local variable or class attribute, because it is not a complete type yet (it's called an incomplete type ), but provided that that is not what is required, you should be able to make it work.

If you need to work with instantiations of a type inside a function body, that is also perfectly doable, provided you define the actual function body after the dependent type has been fully defined. This is normally done by separating class definitions and function implementations into two separate source files, the header ( .h or .hpp ) and code ( .c or .cpp ). The code files need to include all headers that they depend on prior to actually getting into the code.

See When can I use a forward declaration? for an excellent summary of what you can and cannot do with forward-declarations.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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