摘要:寻找标准C ++设计模式,通过构造函数
加载不同的文件我有一个Base
类,其中包含一些将由所有派生类使用的功能(例如Derived_A
,Derived_B
)。主要区别在于Derived_A
和Derived_B
覆盖load
函数,构造函数使用该函数来加载数据文件(load
也可以在构造函数外部显式调用)。
我遇到了一个意想不到的问题:构造函数调用的load
函数将类视为Base
类型,但是当我使用默认构造函数并调用load
时函数显式,然后虚函数表允许调用预期的load
函数。
这闻起来像是一个经典问题,但我无法找到一种方法(我最近用Python编程,我相信,由于打字很弱,总是会调用预期的函数)。
同样,我真的希望Base::load
是纯虚拟/抽象的(只有派生类才会被实例化);但是,这将无法编译(我相信,因为编译器会看到将调用纯虚函数)。
你能帮忙吗?
输出:
加载w /构造函数:
Base :: load file_A
Base :: load file_B加载w /功能后结构:
Derived_A :: load file_A
Derived_B :: load file_B
代码:
#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;
}
答案 0 :(得分:2)
您看到的行为在C ++中已经很好地定义了 - 它在这种情况下没用,因为当您从load(std::string)
调用Base::Base(std::string)
时,类没有完全构建。
有两种直接方法:
<强> A 强>
您可以使用调用load的容器类型(也可以保留字符串)。如果您需要保留实例(例如,他们可能有专门的错误信息),这可能更实用。
class Loader
{
public:
Loader(Base* const p, const std::string& location) : d_base(p)
{
this->d_base->load(location);
}
private:
std::unique_ptr<Base>d_base;
private:
Loader(const Loader&) = delete;
Loader& operator=(const Loader&) = delete;
};
使用中:
std::cout << "Loading w/ Loader:\n";
Loader l_der_a(new Derived_A, "file_A");
Loader l_der_b(new Derived_B, "file_B");
<强>乙强>
您也可以使用辅助函数来处理它:
class Base {
public:
template<typename T>
static void Load(const std::string& x)
{
T().load(x);
}
Base()
{
}
Base(std::string x)
{
/* load(x); << see Load(const std::string&) */
}
virtual ~Base()
{
}
virtual void load(std::string x) = 0;
};
使用中:
std::cout << "Loading w/ Base::Load<T>():\n";
Derived_A::Load<Derived_A>("file_A");
Derived_B::Load<Derived_B>("file_B");
然后还有其他几种方法和变化 - 它取决于最适合您设计的方法。使用C ++,您当然可以选择。
答案 1 :(得分:2)