Вопрос

I'm learning C++ in a class. They have us using Geany on a Virtual Machine with Ubuntu. I miss the powers of an IDE, so I tried several: Netbeans, Eclipse and Code::Blocks.

The code I have for a homework compiles and runs with no problems in Geany on the VM. When I tried all the other IDEs, the compiler gives me an error. I tried Netbeans and Eclipse on Windows 7 and Ununtu in the same VM. In searching for an answer, this help topic says that Geany is doing a lot behind the scenes for me. So I've tried playing with removing the various #include statements I have for the headers and source codes, and solved the problem (Just kidding!) and can't figure out what's really happening.

ArrayBagTester2.cxx: (this is what I compile/run in Geany)

#include <iostream>
#include <string>
#include "ArrayBag.h"

using namespace std;

int main()
    {
        // a bunch of stuff
    }

ArrayBag.h: (provided by the professor with no changes made/needed)

#ifndef _ARRAY_BAG
#define _ARRAY_BAG

#include "BagInterface.h"
template<class ItemType>
class ArrayBag : public BagInterface<ItemType>
{
    private:
        static const int DEFAULT_CAPACITY = 4;
        ItemType* itemArray; //array must be dynamic; so pointers are very yes
        int numberOfItems;
        int myCapacity; //added variable to track capacity

    public:
        ArrayBag(int capacity = DEFAULT_CAPACITY); // new constructor
        ArrayBag(const ArrayBag& anotherBag); // copy constructor
        ~ArrayBag(); //destructor
        int getCurrentSize() const;
        int getCapacity() const;
        void resize(int newCapacity); // resize
        bool isEmpty() const;
        bool isFull() const;
        bool add(const ItemType& newEntry);
        bool remove(const ItemType& anEntry);
        void clear();
        bool contains(const ItemType& anEntry) const;
        int getFrequencyOf(const ItemType& anEntry) const;
        vector<ItemType> toVector() const;
        ArrayBag& operator=(const ArrayBag& anotherBag);
};

#include "ArrayBag.cxx"
#endif

BagInterface.h (Provided by text book author, note copyright. I have crippled to maintain their copyright.)

//  Created by Frank M. Carrano and Tim Henry.
//  Copyright (c) 2013 __Pearson Education__. All rights reserved.

/** Listing 1-1.
    @file BagInterface.h */
#ifndef _BAG_INTERFACE
#define _BAG_INTERFACE

#include <vector>
using namespace std;

template<class ItemType>
class BagInterface
{
public:
   virtual .... stuff here, all virtual functions ...
};
#endif

ArrayBag.cxx: The meat and potatoes and what we're supposed to (solely) edit, errors start at line 9:

#include <vector>
#include <cstddef>
#include <algorithm>

#include "ArrayBag.h"

// Constructor; creates and initializes an empty Bag of "capacity" size
template <class ItemType>
********************//LINE 9:**************************
ArrayBag<ItemType>::ArrayBag(int capacity)
{
    myCapacity = capacity;
    itemArray = new ItemType[myCapacity];
    numberOfItems = 0;
}

// Copy constructor; creates and initializes Bag from another Bag
template <class ItemType>
ArrayBag<ItemType>::ArrayBag(const ArrayBag& anotherBag)
{
    numberOfItems = anotherBag.getCurrentSize();
    myCapacity = anotherBag.getCapacity();
    itemArray = new ItemType[myCapacity];

    for (int i = 0; i < numberOfItems; ++i)
        itemArray[i] = anotherBag.itemArray[i];
}

//destructor
template <class ItemType>
ArrayBag<ItemType>::~ArrayBag()
{
    delete [] itemArray;
}

// Assignment operator
template <class ItemType>
ArrayBag<ItemType>& ArrayBag<ItemType>::operator=(const ArrayBag<ItemType>& anotherBag)
{
    // see if we're trying to assign to ourself, stupid user
    if (&anotherBag == this)
        return *this;
    clear();
    //ArrayBag<ItemType>::~ArrayBag();
    delete [] itemArray;
    //ArrayBag<ItemType>::ArrayBag(anotherBag);
    numberOfItems = anotherBag.getCurrentSize();
    myCapacity = anotherBag.getCapacity();
    itemArray = new ItemType[myCapacity];

    for (int i = 0; i < numberOfItems; ++i)
        itemArray[i] = anotherBag.itemArray[i];

    return *this;
}

// Return the number of Items being stored in the Bag
template <class ItemType>
int ArrayBag<ItemType>::getCurrentSize() const
{
    return numberOfItems;
}

// Return the capacity of the bag (the maximum Items it can store)
template <class ItemType>
int ArrayBag<ItemType>::getCapacity( ) const
{
    return myCapacity;
}

//Resizes the bag's capacity to newCapacity
//if the new size is larger, copy all bag contents
// we don't downsize a bag in HW2
template <class ItemType>
void ArrayBag<ItemType>::resize(int newCapacity)
{
    ItemType* oldArray = itemArray;
    itemArray = new ItemType[newCapacity];
    for(int i = 0; i < myCapacity; ++i)
        itemArray[i] = oldArray[i];
    delete [] oldArray;
}

// Report whether the Bag is empty
// Return true if the Bag is empty (storing no Items);
// Return false if Items exist in the Bag
template <class ItemType>
bool ArrayBag<ItemType>::isEmpty() const
{
    return (numberOfItems == 0);
}

// Report whether the Bag is full
// Return true if the Bag is filled to capacity
// Return false if there is still room
template <class ItemType>
bool ArrayBag<ItemType>::isFull() const
{
    //This bag is resizeable, so it's never full
    return false;
}

// Give the Bag a new Item to store
// If Bag is full, double capacity and add newItem
// Else, Bag must add this Item to its Item array and update its numberOfItems
// If Bag is full after this, return true; else return false
template <class ItemType>
bool ArrayBag<ItemType>::add(const ItemType& newItem)
{
    if (numberOfItems == myCapacity)
    {
        resize(myCapacity * 2);
        myCapacity = myCapacity * 2;
    }

    itemArray[numberOfItems++] = newItem;

    //This bag is resizeable, so it's never full
    return false;
}

// Make the Bag act like an empty Bag again
template <class ItemType>
void ArrayBag<ItemType>::clear()
{
    numberOfItems = 0;
}

// Remove an Item from the bag
// If Item is not there, nothing changes and we return false
// Else, we fill in its spot in that Item array and count number of Items down
template <class ItemType>
bool ArrayBag<ItemType>::remove(const ItemType& anItem)
{
    for (int i = 0; i < numberOfItems; ++i)
    {
        if (itemArray[i] == anItem)
        {
            itemArray[i] = itemArray[--numberOfItems];
            return true;
        }
    }
    return false;
}

// Check if an Item is in the Bag
// Return true if it is in the Bag, and false if not
template <class ItemType>
bool ArrayBag<ItemType>::contains(const ItemType& anItem) const
{
    for (int i = 0; i < numberOfItems; ++i)
        if (itemArray[i] == anItem) return true;
    return false;
}

// Check how many times an Item is in the Bag
// return 0 if it's not there; otherwise,
// return the number of times it occurs
template <class ItemType>
int ArrayBag<ItemType>::getFrequencyOf(const ItemType& anItem) const
{
    int frequency = 0;

    for (int i = 0; i < numberOfItems; ++i)
        if (anItem == itemArray[i]) ++frequency;

    return frequency;
}

// Make an output vector of Items from the bag (for checking)
template <class ItemType>
vector<ItemType> ArrayBag<ItemType>::toVector() const
{
    vector<ItemType> bagContents;

    for (int i = 0; i < numberOfItems; ++i)
        bagContents.push_back(itemArray[i]);

    return bagContents;
}

Here is the error generated for each method in the ArrayBag.cxx:

C:\Users...\HW2\ArrayBag.cxx|9|error: redefinition of 'ArrayBag::ArrayBag(int)'| C:\Users...\HW2\ArrayBag.cxx|9|error: 'ArrayBag::ArrayBag(int)' previously declared here

... Truncated for clarity ...

I would like to understand:

  1. Why does Geany work when the others do not? What really is that make makefile magic?
  2. Is there an (easy) fix to Netbeans (not that Netbeans is causing the problem) on Windows to fix this? (I seem to prefer Netbeans, no other reason.) or:
  3. What is a more traditional or standard way of including these relationships and files?
Это было полезно?

Решение

The file ArrayBag.cxx is included (which is very strange way of doing it but whatever) and is not meant to be compiled. Just compile ArrayBagTester2.cxx and it should be ok.

By the way: I agree with the previous comment that this thing is a monstrosity...

Другие советы

You shouldn't be compiling ArrayBag.cxx as a separate compilation unit. See here:

Why can templates only be implemented in the header file?

Template implementation files are not separate compilation units, but your command-line suggests that it was compiled as one.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top