C ++ - 如何更新同一个类的实例之间的指针(或成员)

时间:2015-07-17 15:24:08

标签: c++ pointers


我有一个简单的类,它包含void指针和int(这是某种boost::Variant教育项目。)
我还有一个工作副本构造函数和析构函数。

但是我的研究结果是,我将如何完成这样的事情:

Container cont1("some value"); //simple construction
Container cont2;
cont2.createLink(cont1); //this should initialize members with a reference (or something alike)
std::cout<<cont1; //yields "some value"

cont2.set(20); //setting this container should update the original container too, since I initialized with a reference (or smth alike)
std::cout<<cont1; //yields 20

这是该类的简化版本:

class Container {
    public:
        Container(){}
        Container(const std::string &val){var.type = STRING; var.data = new std::string(val);}
        Container(int val){ /* same for int */}
        Container(const Container &val){ /* do a memory copy */}

        void set(int val){ /* set the value if type matches, otherwise allocate a new pointer */}
        void set(const std::string &val){ /* the same as for int */}
        void createLink(const Container &val){ /* somehow assign a reference or whatsoever */}
    private:
        typedef struct VAR {
            int type = 0;
            void *data = NULL; }       
        VAR var;
}

如果我将cont2的值设置为string(即此刻它保持的数据类型相同),一切都很好,因为该集合不会分配新的指针而是分配一个新的价值 但是,如果我为cont1分配不同的值并因此必须分配新指针,如何确保cont2的指针更新?

我需要像shared_pointer这样的东西吗?

感谢您的任何见解!

修改

我改为功能名称,以便更清楚地说明应该发生什么。

2 个答案:

答案 0 :(得分:1)

有一种解决方案只涉及直接OO。您可以为变量类型创建一个接口,并使用double间接到变量实例,以允许链接的容器共享相同的变体实例。

需要双重间接的原因是,如果新类型与原始类型不匹配,您希望set()方法自动分配新变体实例的方式。如果我们只是从两个容器共享一个指向变量的指针,那么在set()创建一个新的变量实例之后,每个容器将再次引用不同的实例。

为了解决这个问题,我们可以使用指针指向容器中变体的指针。

以下是定义变体界面的可能方法,以及如何将其子类化:

typedef std::ostream Out;
struct BadType {};

struct Var {
    virtual ~Var () = default;
    virtual Out & print (Out &os) { return os << "(BadType)"; }
    virtual void set (int) { throw BadType(); }
    virtual void set (const std::string &) { throw BadType(); }
};

struct VarInteger : Var {
    int data;
    VarInteger (int v) : data(v) {}
    Out & print (Out &os) { return os << data; }
    void set (int v) throw() { data = v; }
};

struct VarString : Var {
    std::string data;
    VarString (const std::string &v) : data(v) {}
    Out & print (Out &os) { return os << data; }
    void set (const std::string &v) throw() { data = v; }
};

以下是如何定义指向指针的方法,以及如何初始化指针:

typedef std::shared_ptr<Var> VarPtr;
std::shared_ptr<VarPtr> varptr_;

static VarPtr make_var () { return std::make_shared<Var>(); }
static VarPtr make_var (int v) { return std::make_shared<VarInteger>(v); }
static VarPtr make_var (const std::string &v) {
    return std::make_shared<VarString>(v);
}

VarPtr & var () { return *varptr_; }
const VarPtr & var () const { return *varptr_; }

Container () : varptr_(std::make_shared<VarPtr>(make_var())) {}
Container (int v) : varptr_(std::make_shared<VarPtr>(make_var(v))) {}
Container (const std::string &v)
    : varptr_(std::make_shared<VarPtr>(make_var(v))) {}

以下是您的set()方法和createLink()方法的实施方式。

void set (int v) {
    try { var()->set(v); }
    catch (BadType) { var() = make_var(v); }
}

void set (const std::string &v) {
    try { var()->set(v); }
    catch (BadType) { var() = make_var(v); }
}

void createLink (const Container &val) { varptr_ = val.varptr_; }

Demo

答案 1 :(得分:0)

以下内容如何?当然createLink不能不接受const引用,所以我把它作为一个非const指针。

class Container {
    const int STRING    = 0x0000001;
    const int INT       = 0x0000002;

    const int LINK      = 0x8000000;

public:
    ...    
    void set(int val){...}
    void set(const std::string &val)
    { 
        if (var.type == LINK) 
        {
            reinterpret_cast<Container*>(var.data)->set(val);
        }
        else
            ...
    }
    void createLink(Container* val)
    {
        var.data = val;
        var.type = LINK;
    }
private:
    typedef struct VAR {
        int type = 0;
        void *data = NULL;
    };
    VAR var;
};

要考虑一些重要的观点 - 链接的相对生命周期和链接是最明显的。