How to access derived class members from virtual base class object?
Feb 16, 2019 at 8:50pm UTC
I'm writing a program that uses a base class with a constructor that takes a bool variable. If the bool is true then it will create a dynamic array, if false it will create a linked list. So far I've just written the implementation for the dynamic array derived class, but I can't seem to figure out how I should make an object correctly use the bag constructor to create a DAbag object. Is what I have here correct? I have the Source.cpp, which is where I'll test the classes, bagb.cpp, which has the derived classes, and bagb.h, which has the base class.
Source.cpp :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
#include "bagb.h"
#include <iostream>
using namespace std;
using namespace bag_hierarchy;
int main()
{
bool pass = true ;
bag daptr(pass);
daptr = daptr->create(true );
daptr->insert(42);
daptr->insert(36);
}
bagb.h :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
#ifndef BAG_BASE_H
#define BAG_BASE_H
#include <cstdlib> // Provides size_t
namespace bag_hierarchy
{
class bag
{
public :
// TYPEDEFS and MEMBER CONSTANTS
typedef int value_type;
typedef std::size_t size_type;
//static const size_type DEFAULT_CAPACITY = 30;
// CONSTRUCTORS and DESTRUCTOR
//bag(size_type initial_capacity = DEFAULT_CAPACITY);
//bag(const bag& source);
//factory method to construct derived class objects
bag()
{
}
bag(bool daORll)
{
if (daORll)
{
DAbag();
}
}
static bag* create(bool daORll)
{
if (daORll)
{
DAbag *daptr;
return daptr;
}
else
{
LLbag *llptr;
return llptr;
}
}
/*bag(bool input)
{
value = input;
create(value);
}*/
//mimic a virtual copy constructor
virtual bag* clone(const bag& source) = 0;
//virtual destructor
virtual ~bag() {};
// MODIFICATION MEMBER FUNCTIONS
//void reserve(size_type new_capacity);
virtual bool erase_one(const value_type& target) = 0; //DA
virtual size_type erase(const value_type& target) = 0; //DA
virtual void insert(const value_type& entry) = 0; //DA
//virtual void operator +=(const bag& addend) = 0;
virtual void operator =(const bag& source) = 0; //DA
// CONSTANT MEMBER FUNCTIONS
virtual size_type size( ) const = 0; //DA
virtual size_type count(const value_type& target) const = 0; //DA
private :
};
// NONMEMBER FUNCTIONS for the bag class
bag operator +(const bag& b1, const bag& b2);
}
#endif
bagb.cpp :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
#include "bagb.h"
#include <iostream>
using namespace std;
namespace bag_hierarchy
{
class DAbag : public bag
{
public :
size_t const capacity = 50;
size_t used = 0;
bool * in_use;
value_type* data;
DAbag()
{
in_use = new bool [capacity];
data = new value_type[capacity];
}
void insert(const value_type& entry)
{
if (size() < capacity)//checks to make sure that we aren't about to go over CAPACITY
{
for (size_t loop = 0; loop < capacity; loop++)//checks each member of the in_use array
{
//cout << "/ " << in_use[loop] << "/\n";
if (!in_use[loop])//checks to see if the current slot is empty
{
in_use[loop] = true ;//sets the loop'th member of the in_use array to true
++used;//adds one item to amounts of items in bag
data[loop] = entry;//inserts the item into the currently empty slot
//if (loop == 0)
//{
// return loop; COMMENTED OUT UNTIL I KNOW RECEIPTS ARE NEEDED
//}
//else
//{
// return loop - 1;//returns the receipt
//}
//also check out this CLEAN concatenation
}
}
}
else
{
cout << "Bag is Full!\n" ;
}
return ;
}
size_type size() const { return used; }
bool erase_one(const value_type& target)
{
if (target <= capacity)
{
in_use[target] = false ;
data[target] = 0;
used--;
return true ;
}
return false ;
}
size_type erase(const value_type& target)
{
for (int i = 0; i < capacity; i++)
{
if (in_use[i] == true )
{
if (data[i] == target)
{
in_use[i] = false ;
data[i] = 0;
used--;
}
}
}
}
size_type count(const value_type& target) const
{
size_type occur;
occur = 0;
for (int i = 0; i < used; i++)
{
if (in_use[i] == true )
{
if (data[i] == target)
{
occur += 1;
}
}
}
return occur;
}
void operator =(const bag& source)
{
used = source.
for (int i = 0; i < capacity; i++)
{
in_use[i] = source.in_use[i];
data[i] = source.data[i];
}
}
bag* clone(const bag& source)
{
bag* cloneHold;
cloneHold = cloneHold->create(true );
cloneHold->used = source.used;
for (int i = 0; i < capacity; i++)
{
cloneHold->in_use[i] = source.in_use[i];
cloneHold->data[i] = source.data[i];
}
return cloneHold;
}
void display()
{
cout << "These are the contents of this object: " << used << " " << capacity << "\n" ;
for (int i = 0; i < capacity; i++)
{
cout << i << " : " << in_use[i] << " : " << data[i] << "\n" ;
}
}
};
Feb 17, 2019 at 9:49am UTC
Hello Toasthat
Why do you think that you need a bool for the constructor?
You already have the bool in your create() function where you actually make the decision which type of object to create. Thus, I would think the constructor with the bool is unnecessary.
Feb 17, 2019 at 4:14pm UTC
You need a better understanding of pointers.
1 2
bag daptr(pass);
daptr = daptr->create(true );
->
is for pointers. Use
.
instead.
1 2
DAbag *daptr;
return daptr;
This returns an uninitialized pointer.
Your create() method should allocate the bag on the heap:
1 2 3 4 5 6 7
static bag* create(bool daORll)
{
if (daORll) {
return new DAbag;
} else {
return new LLbag;
}
Because the method is static, you don't actually need an instance to call it, so in main() you can do:
bag *daptr = Bag::create(true );
Some other comments:
1 2 3
bool erase_one(const value_type& target)
{
if (target <= capacity)
Since target is a value, it makes no sense to compare it to capacity. I'd implement erase() and erase_one using a private method:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
private :
// Erase elements equal to "target". This erases all matching items
// or just one, depending on "justOne"
size_type doErase(const value_type& target, bool justOne)
{
size_t result = 0;
for (int i = 0; i < capacity; i++) {
if (in_use[i] == true && data[i] == target) {
in_use[i] = false ;
data[i] = 0;
used--;
++result;
if (justOne) break ;
}
}
return result;
}
public :
size_t erase(const value_type &target) { return doErase(target, false ); }
bool erase_one(const value_type target) {return doErase(target, true ); }
void operator =(const bag& source)
Since source could be an LLbag, you need to implement this using only the public interface. Put another way LLbag might not have
in_use
and
data
members, so you can't use them.
Topic archived. No new replies allowed.