gpt4 book ai didi

C++ 设计模式 : multiple ways to load file

转载 作者:太空狗 更新时间:2023-10-29 21:05:28 26 4
gpt4 key购买 nike

总结:寻找通过构造函数加载不同文件的标准C++设计模式

我有一个 Base 类,它具有一些将被所有派生类(例如 Derived_ADerived_B)使用的功能。主要区别在于 Derived_ADerived_B 覆盖了 load 函数,构造函数使用该函数加载数据文件(load 也可以在构造函数之外显式调用)。

我由此遇到了一个意想不到的问题:构造函数调用的load函数将类视为Base类型,但是当我使用默认构造函数并调用load 函数,然后虚函数表允许调用预期的 load 函数。

这听起来像是一个经典问题,但我想不出解决这个问题的方法(我最近在用 Python 编程,我相信,由于弱类型,它总是会调用预期的函数)。

同样,我真的很希望 Base::load 是纯虚拟的/抽象的(只有派生类会被实例化);但是,这不会编译(我相信,因为编译器认为将调用纯虚函数)。

你能帮忙吗?

输出:

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

代码:

#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;
}

最佳答案

您看到的行为在 C++ 中得到了很好的定义——它在这种情况下没有用,因为当您从 Base 调用 load(std::string) 时,类没有完全构建::Base(std::string).

有两种直接的方法:

一个

您可以使用调用 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");

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++,您当然有多种选择。

关于C++ 设计模式 : multiple ways to load file,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9834354/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com