Summary: In search of the standard C++ design pattern for loading different files via constructor
I have a Base
class with some functionality that will be used by all derived classes (e.g. Derived_A
, Derived_B
). The principal difference is that Derived_A
and Derived_B
override the load
function, which is used by the constructor to load a data file (load
may also be called explicitly outside the constructor).
I ran into an unexpected problem from this: the load
function called by the constructor treats the class as the Base
type, but when I use a default constructor and call the load
function explicitly, then the virtual function table permits the intended load
function to be called.
This smells like a classic problem, but I can't figure out a way to do it (and I was most recently programming in Python, which I believe, due to weak typing, would always call the intended function).
In the same vein, I'd really like Base::load
to be pure virtual / abstract (only derived classes will be instantiated); however, that won't compile (I believe, because the compiler sees that the pure virtual function will be called).
Can you help?
Output:
Loading w/ constructor:
Base::load file_A
Base::load file_B Loading w/ function post construction:
Derived_A::load file_A
Derived_B::load file_B
Code:
#include <iostream>
#include <string>
class Base
{
public:
Base() {}
Base(std::string x)
{
load(x);
}
virtual void load(std::string x)
{
std::cout << "\tBase::load " << x << std::endl;
}
};
class Derived_A : public Base
{
public:
Derived_A() {}
Derived_A(std::string x): Base(x) {}
void virtual load(std::string x)
{
std::cout << "\tDerived_A::load " << x << std::endl;
}
};
class Derived_B : public Base
{
public:
Derived_B() {}
Derived_B(std::string x): Base(x) {}
void virtual load(std::string x)
{
std::cout << "\tDerived_B::load " << x << std::endl;
}
};
int main()
{
// simpler code, but it doesn't behave as I hoped
std::cout << "Loading w/ constructor:" << std::endl;
Base*der_a = new Derived_A(std::string("file_A"));
Base*der_b = new Derived_B(std::string("file_B"));
// this is what I want to do
std::cout << "Loading w/ function post construction:" << std::endl;
der_a = new Derived_A;
der_a->load( std::string("file_A") );
der_b = new Derived_B;
der_b->load( std::string("file_B") );
return 0;
}