C ++设计模式:多种方式加载文件 [英] C++ design pattern: multiple ways to load file

查看:84
本文介绍了C ++设计模式:多种方式加载文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

摘要:通过构造函数搜索用于加载不同文件的标准C ++设计模式

Summary: In search of the standard C++ design pattern for loading different files via constructor

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

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).

我遇到了一个意外的问题:由构造函数调用的 load 函数将该类视为 Base 类型,但是当我使用默认构造函数并显式调用 load 函数时,虚函数表允许 load 函数被调用。

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.

这闻起来像一个经典的问题,但我无法想出办法(最近我在Python中编程,我相信,由于弱打字,总是调用预期的功能)。

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).

同样,我真的希望 Base :: load 成为纯虚拟/抽象(仅限于派生类将被实例化);然而,这不会编译(我相信,因为编译器看到纯虚拟函数将被调用)。

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).

你能帮助吗?

输出:


加载w /构造函数:

Base :: load file_A

Base :: load file_B载入/功能帖子结构:

Derived_A :: load file_A

Derived_B :: load file_B

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)

The behavior you see is well defined in C++ -- it's just not useful in this scenario because the class is not fully constructed when you call load(std::string) from Base::Base(std::string).

有两种即时方法:

A

您可以使用一种调用加载的容器类型(也可能持有该字符串)。如果您需要持有实例(例如,他们可能会有专门的错误信息),这可能更实用。

You could use a container type which calls load (and perhaps holds on to the string as well). This may be more practical if you need to hold on to instances (e.g. they may have specialized error information).

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

你也可以使用辅助函数来处理它:

You could also approach it using a helper function:

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 ++,您当然可以选择。


And then there are several other approaches and variations - it depends on what fits your design best. With C++, you certainly have options.

这篇关于C ++设计模式:多种方式加载文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆