samedi 29 octobre 2016

Object do not have a fields that have been set into the overriden operator new without define constructor into the derived class

I have a problem with undersending how work override operator new. I have the base class Task with a overridden operator new:

void* operator new(size_t bytes, const allocate_continuation_proxy& p);

This operator is used for allocate a new task and set private fields from current working task. allocate_continuation_proxy& is refer to current task.

class allocate_continuation_proxy; 

class Task { 
public: 
    virtual ~Task() { 
    } 

    void* operator new(size_t size) { 
        return ::operator new(size); 
    } 

    void* operator new(size_t bytes, const allocate_continuation_proxy& p); 

    allocate_continuation_proxy& allocate_continuation() { 
        return *reinterpret_cast<allocate_continuation_proxy*>(this); 
    } 

    virtual Task* Compute() = 0; 

    inline Task* Continuation() { 
        return _continuation; 
    } 

    inline void Continuation(Task& task) { 
        _continuation = &task; 
    } 

    inline void ContinuationAsNull() { 
        _continuation = nullptr; 
    } 

protected: 
    Task() { 
    } 

private: 
    Task* _continuation; 
    Ct* _cancellationToken; 
}; 

class allocate_continuation_proxy { 
public: 
    Task& allocate(size_t size) const; 
}; 

inline Task& allocate_continuation_proxy::allocate(size_t size) const { 
    Task& t = *((Task*)this); 
    Task* c = (Task*) ::operator new(size); 
    c->CancellationToken(nullptr); 
    c->Continuation(*t.Continuation()); 
    c->PendingCount(0); 
    t.ContinuationAsNull(); 
    return *c; 
} 

inline void* Task::operator new(size_t bytes, const allocate_continuation_proxy& p) { 
    return &p.allocate(bytes); 
} 

I try to execute this code:

class C0 : public Task { 
public: 
    //C0() { 
    //} 

    Task* Compute() override { 
        std::cout « "C0 is computing..." « std::endl; 
        Task* c = Continuation() 
        c->Compute(); //if constuctor C0() is not been to define, this line throw exception because "c" = nullptr, but "c" has to point on instance of C2
        return nullptr; 
    } 
}; 

class C2 : public Task { 
public: 
    Task* Compute() override { 
        std::cout « "C2 is computing..." « std::endl; 
        return nullptr; 
    } 
}; 

class C1 : public Parallel::Task { 
public: 
    Task* Compute() override { 
        std::cout « "C1 is computing..." « std::endl; 
        C0& c = *new (allocate_continuation()) C0(); 
        c.Compute(); 
        return nullptr; 
    } 
}; 

int main() { 
    C1& c1 = *new C1(); 
    c1.Continuation(*new C2()); 
    c1.Compute(); 
    return 0; 
} 

My problem is into the this line:

C0& c = *new (allocate_continuation()) C0(); 

If constuctor C0() is not been to define, refer "c" does not have _continuation that has been set into the allocate_continuation_proxy::allocate(size_t size). But If I define a constructor into the class C0, refer "c" will have a _continuation. I don`t understand why? And How can I get the correct behavior without defining a constructor into the derived class?

Aucun commentaire:

Enregistrer un commentaire