2015-04-08 109 views
2

我遇到问题,我在类“List”中有一个指向基类对象“元素”的指针。在某些情况下,我需要Element是一个更专门的类型“过渡”。过渡来源于元素。但是当我从指向Element对象的指针创建一个Transition对象时,指针现在与我的矩阵类List脱钩。与基础对象位于相同位置的派生对象

在我迄今为止的研究中,我已经读过,但这是创建派生对象的方式。 但这不是我想到的......我想让派生对象与基类指针(指向Element类的指针,“last”)位于相同的位置。 我该怎么做?

示例代码:

#include <iostream> 


class Element{ 

    public: 

     Element(){ 
      member = 0; 
     } 

     virtual void set_member(int i){} 

     void print_member(){ 
     std::cout << member << std::endl; 
    } 

    protected: 
     int member; 

}; 


class Transition: public Element{ 

    public: 
     void set_member(int i){ 
      member = i; 
     } 

}; 


class List{ 

    public: 

    List(){ 
     last = new Element; 
    } 

    Element* get_last(){ 
      return last; 
     } 

    void print(){ 
     last->print_member(); 
    } 

    private: 
     Element* last; 

}; 

int main(){ 

    List list; 
    Element* last = list.get_last(); 
    last = new Transition; // creates completely new entity. 
          // I wanted to make a derived object 
          // from Element at the same location 
          // as the Elememt object though 
    last->set_member(1); 
    last->print_member(); // returns newly assigned value 
    list.print(); // returns default value of Element type 
        // but I wanted itto return newly assigned value 

} 
+0

请注意,您的代码书面至少有两个内存泄漏。这可能是值得描述你实际尝试做什么的,这样你可以找到解决你真正问题的答案(即你解决方案的方式)。 – Lionel

+0

那么,我真正想要做的是通过最后一个指针来访问列表的最后一个元素,这个指针是我的列表类的一个属性。然后我想更改最后一个列表元素的属性。 –

回答

3
Element* last = list.get_last(); 
last = new Transition; 

现在局部变量last无关,在List类做的成员变量last,所以对局部变量的行为不会影响到成员变量last。您可能需要使用settor方法来设置它。如:

class List { 
public: 
    void set_last(Element* e) { 
     last = e; 
    } 

    // ... 
}; 

然后在main

int main() { 
    List list; 
    Element* last = new Transition; // creates completely new entity. 
    last->set_member(1); 
    list.set_last(last);   // set it back to List 
    list.print(); 
} 

[编辑]
BTW:你在你的List类使用原始的指针,你需要注意的管理它。例如,你应该在delete它的析构函数中,并且在它之前设置一个新的指针,delete旧的指针,等等。一般来说,通过使用智能指针(如std::unique_ptr)来采用RAII成语是更好的解决方案。

+0

我明白了,谢谢。 我非常沉迷于我的想法,我完全洞悉这个明显的解决方案。 –

2

我希望派生的对象与基类指针(指向Element类的指针,“last”)位于相同的位置。我将如何做到这一点?

让我明白你在做什么。

您有:

Element* last = list.get_last(); 

在这一点上,last指向一个有效的对象要么是Element或分型Element

现在你想创建一个Transition对象,并且希望该对象的地址与对象的地址last指向的地址相同?

简短的回答:不这样做

龙答:

是的,你可以这样做,使用placement new operator

但是,您必须先了解有关内存位置的所有信息,然后才能使用它。

  1. 您必须知道该位置有足够的内存来容纳Transition对象。

  2. 住在那里的对象的生命必须通过调用它的析构函数来终止。

  3. 程序的其他部分不会尝试使用先前的对象类型访问该内存位置。

  4. 您不能在指针上调用deletedelete必须在new返回的相同指针类型上调用。否则,你将处于未定义的行为领域。

  5. 如果内存是使用new []运算符分配的,则必须使用运算符delete []释放内存。如果内存是使用普通的new运算符分配的,则必须使用普通的delete运算符重新分配内存。

可能还有更多的陷阱我不一定记得。

+0

谢谢,那么这种方法显然超出了我目前的理解水平。 –

0

首先,正如其他人所说..我认为这需要重新考虑一点。

但鉴于你问的问题,认识到这一点:

Element* get_last(){ 
     return last; 
    } 

返回一个指针到最后(你new'd的东西),但你并不想改变最后,你正在寻找将指针更改为最后。这可以这样做:

Element** get_last(){ 
     return &last; 
    } 

这将返回指向元素指针的指针。然后你可以将该指针设置为一个新的对象,但是要意识到如果你这样做了,那么你刚刚泄露了你最初创建的元素的内存。你新增的一切必须删除(即使你使用上面的songyuanyao的评论..确保你删除了set_last和列表析构函数中的旧元素)。所以,你会结了:

Element ** last = list.get_last(); 
delete(*last); // Removes the old entity from memory. 
*last = new Transition; // creates completely new entity. 

我能想到的任何情况下,我会写这虽然..它确实像你需要一些重新分解似乎我的。

0

我意识到我正以过度复杂的方式接近我的问题。

我的解决方案现在是这样的:

#include <iostream> 


class Element{ 

    public: 

     Element(){ 
      member = 0; 
      successor = 0; 
     } 

     virtual void set_member(int i){} 

     virtual void set_successor(int successor){} 

     void print(){ 
     std::cout << member << std::endl; 
     std::cout << successor << std::endl; 
    } 

    protected: 
     int member; 
     int successor; 

}; 


class Transition: public Element{ 

    public: 
     void set_member(int i){ 
      member = i; 
     } 

     void set_successor(int i){ 
      successor = i; 
     } 

}; 


class List{ 

    public: 

    List(){ 
     last = new Transition; 
    } 

    Element* get_last(){ 
      return last; 
    } 

    void set_last(Element* new_last){ 
     last = new_last; 
    } 

    void print(){ 
     last->print(); 
    } 

    private: 
     Element* last; 

}; 

int main(){ 

    List list; 
    (list.get_last())->set_member(6); 
    (list.get_last())->set_successor(8); 
    list.print(); 

} 
相关问题