用C ++初始化另一个对象

时间:2016-02-18 10:11:52

标签: c++ initialization loader friend resource-management

在我的项目中,我有可以从不同格式加载和重新加载的Resource对象。加载算法在不同的ResourceLoader子类中实现。

class Resource
{
private:

    // Not for client access    
    Type1 InternalData1;
    Type2 InternalData2;
    TypeN InternalDataN;

    ResourceLoader Loader;

public:

    // Any client interface
    void UseResource();
};

class ResourceLoader
{
public:

    void Load(Resource& R) = 0;
};

class ResourceLoaderFormat1: public ResourceLoader
{
public:

    void Load(Resource& R) { ...loads Resource from Format1... }
};    

class ResourceLoaderFormat2: public ResourceLoader
{
public:

    void Load(Resource& R) { ...loads Resource from Format2... }
};

Loader以给定格式读取输入并初始化其目标Resource对象R. Loader存储在资源中,因此如果资源变为无效,则使用存储的加载器重新加载自身。

问题是Loader应该如何初始化资源?

  1. 将所有InternalData字段设为公开。它授予客户端访问权限,但这并不好。
  2. 让Loader成为Resource的朋友。特定格式的每个新加载器都将添加到资源头中,从而消除了可扩展性,并要求任何编写扩展的程序员触摸基本代码。
  3. 为每个InternalData提供setter。将所有这些公开发布不远,因为任何客户都可以更改数据,但不得更改。
  4. 提供Resource :: Setup(InternalData1,InternalData2,InternalDataN),或将它们全部包装在某个结构中并传递该结构。与3.相同,但一次设置所有字段。
  5. 问题在于,必须可以访问Resource类字段,以便从可扩展的类集中进行写入,并且必须无法访问客户端代码。有没有好的OOP解决方案?感谢。

2 个答案:

答案 0 :(得分:1)

假设我们选择

  

让Loader成为Resource的朋友。

有缺点

  

特定格式的每个新加载器都将添加到资源标头中,从而消除了可扩展性,并要求任何编写扩展程序的程序员触摸基本代码。

但是,由于您将加载器拆分为基类+派生类,因此您只能授予对Loader的访问权限,并通过Loader成员授予protected子类访问权限。

class Resource
{
    Type1 InternalData1;
    ...
    friend class ResourceLoader;
};

class ResourceLoader
{
    ...
protected:
    static void setResourceInternalData1(Resource &r, const Type1 &val1);
    ...
};

所有ResourceLoader子类现在都可以访问这些setter,因为它们是protected

class ResourceLoaderFormat1: public ResourceLoader;
class ResourceLoaderFormat2: public ResourceLoader;

只要您不经常更改Resource的数据成员,这将很有效。

答案 1 :(得分:1)

另一种解决方案是(如我的第一条评论所述):

class ResourceClient
{
    public:
        virtual void UseResource() = 0;
}
class ResourceLoader
{
    public:
         virtual void SetResource() = 0;
}
class Resource:
    public ResourceClient,
    public ResourceLoader
{
private:

    // Not for client access    
    Type1 InternalData1;
    Type2 InternalData2;
    TypeN InternalDataN;

    ResourceLoader Loader;

public:

    // Any client interface
    virtual void UseResource();
    virtual void SetResource();
};

class ResourceLoader
{
public:

    void Load(ResourceLoader& R) = 0;
};

class ResourceLoaderFormat1: public ResourceLoader
{
public:

    void Load(ResourceLoader& R) { ...loads Resource from Format1... }
};    

class ResourceLoaderFormat2: public ResourceLoader
{
public:

    void Load(ResourceLoader& R) { ...loads Resource from Format2... }
};

需要编写的函数集资源使用ResourceLoader指针和restrected函数将使用ResourceClient指针访问资源。

此解决方案的优点是您不需要使用写访问权限声明任何类或函数。 Juste根据您的需要或想要的功能使用正确的界面