user3470131
user3470131

Reputation: 21

Polymorphism: accessing derived class elements from a base class array

I haven't worked with derived classes and polymorphism in a while, and I can't figure out how to access a derived class data item.

// Quick example
class Base {
  string data1;  // data1 = "FOO"
};
class ChildA : public Base {
  string data2;
};


int main() {
Base **list;
list = new Base*[1];
base[0] = new ChildA(// data2 = "BAR");
std::cout << base[0]->data1; // FOO
std::cout << base[0]->data2; // Error; no member named "data2" in Base

Is it possible to retrieve the derived data from the base class array?

Upvotes: 1

Views: 1609

Answers (3)

Richard Hodges
Richard Hodges

Reputation: 69892

If the base class interface must have knowledge of data potentially held in a derived class, here is one of the few ways that is not horribly dangerous.

#include <iostream>
#include <vector>
#include <utility>
#include <memory>
#include <stdexcept>

using namespace std;

class Base {
public:
    Base(std::string d1 = {"FOO"} ) : _data1 { std::move(d1) } {}
    virtual ~Base() = default; // because polymorphism without a virtual base class is naughty
    const string& data1() const { return _data1; }

    virtual bool has_data2() const { return false; }
    virtual const string& data2() const {
        throw invalid_argument {"I don't have data2"};
    };

private:
    string _data1;  // data1 = "FOO"
};

class ChildA : public Base {
public:
    ChildA(std::string d2, std::string d1 = {"FOO"})
    : Base { std::move(d1) }
    , _data2 { std::move(d2) }
    {}

    bool has_data2() const override { return true; }
    const std::string& data2() const override {
        return _data2;
    };

private:
    string _data2;
};

int main()
{
    vector<unique_ptr<Base>> bases;
    bases.push_back(unique_ptr<Base>(new ChildA("bob")));
    bases.push_back(unique_ptr<Base>(new Base("not foo")));

    for(const auto& p : bases) {
        cout << p->data1() << ", " << (p->has_data2() ? p->data2() : "no data 2") << endl;
    }

    return 0;
}

Upvotes: 0

BufBills
BufBills

Reputation: 8103

class member variable by default is private. by using base class pointer, you can not get derived class member var at all.

If you would like to do so, you may want to implement virtual getter function, it will help you getting private member function from derived class.

Upvotes: 0

Aasmund Eldhuset
Aasmund Eldhuset

Reputation: 37950

When you're looking at an instance of a derived class through a pointer to the base class, you can only see the members of the base class, because generally, you wouldn't know what subtype instance you are looking at. The point of polymorphism and virtual functions is that in many cases, you can work with subtype instances without knowing their actual type. For instance, if you want to print information about an instance, and you want data2 to be included when you print a ChildA, you would create a virtual toString() function in Base and override it in ChildA to include data2. Then, you can call toString() without knowing the actual type, and if your instance is actually a ChildA, you'll get data2.

Upvotes: 3

Related Questions