将继承的类类型作为参数传递

时间:2014-04-21 11:41:01

标签: c++ inheritance methods

我将继承的类类型作为参数传递给采用其基类类型的方法时遇到了问题。

class Base {...}
class Derived : public Base {...}
class Container {
    vector<Base*> cont; //1
 public:
    void addToCont(Base x) { //2
        cont.push_back(&x);
    }
}

int main() {
   Container c;
   c.addToCont(Derived(p1,p2)); //3
}

1)我想我需要拥有指向对象的指针容器以保持其正常工作

2)以下是从Derived转换为Base

的错误

3)我不应该改变这个电话。我试过了

Derived d(p1,p2);
c.addToCont(d);

addToCont(Base& x)

它对我有用。

我的问题是我有3个派生类,而且我不想超载add方法3次。我想我将不得不为这些类添加一些虚拟方法或一些类型转换,但我无法找到任何相关内容。我是继承的新手,对此很困惑。谢谢你的帮助。

2 个答案:

答案 0 :(得分:0)

派生类只有在引用或指针时才“可以使用”。如果将类转换为没有引用或指针的基类,则以后将无法将其用作派生类。

如果你实际上是在容器中存储指针,那么我会明确指出,所以:

class Container {
    vector<Base*> cont;
 public:
    void addToCont(Base* x) { 
        cont.push_back(x);
    }
    ~Container()
    {
       for(auto a : cont)
       {
           delete a;
       }
    }
}

主要是:

集装箱c;    c.addToCont(new Derived(p1,p2));

请注意,在原始代码中,Derived(p1, p2)将在调用addToCont(...)后再次被销毁,因此您的数组将指向Derived类的“dead”元素。这可能不是你真正想要的(因为它使用该元素是未定义的行为,并且构建一个装满无用元素的容器是没有意义的)

答案 1 :(得分:0)

一些注意事项:

  1. 必须使用指向Base的指针向量,以便您可以处理层次结构中的对象。不言而喻,使用某种智能指针代替原始指针可能会更好,但这取决于偏好以及您喜欢冒多少风险。
  2. 使用void addToCont(Base x)是错误的,因为即使你只是添加一个Base对象,你也会添加一个指向局部变量的指针(pass-by-value参数)
  3. 使用void addToCont(Base &x)使用本地Derived d的方式也是错误的,出于与以前相同的原因,只要d超出范围,您就会离开指针存储在指针中的悬空指针
  4. 调用addToCont(Derived(...))会传递一个临时对象。当你考虑你的记忆管理时,必须考虑到这一点。
  5. 不确定为什么您认为需要为所有派生类重载addToCont,这不是您在void addToCont(Base &x)
  6. 上所做的
  7. 解决方案(如果你保留原始指针)是void addToCont(Base *x)那里你可以传递指向Base或任何Derived的指针。同样,你必须注意内存管理。您的Derived对象可能需要使用new Derived(...)进行分配,您必须查看谁拥有它,以及谁负责删除它(例如,当Container对象被销毁时)。
  8. 您可能应该记得将虚拟机作为Base的析构函数,因为您将从Base指针中销毁Derived对象,如果析构函数不是虚拟的,则该对象将仅被部分销毁。
  9. 如果绝对需要addToCont(Derived(...))调用,那么您可能需要考虑使用void addToCont(Base &x)定义....但是,它们必须在将对象插入向量之前克隆该对象:

    void addToCont(const Base &x) { //2
        cont.push_back(x.clone());
    }
    

    但是......你需要在Derived类中实现(至少)一个virtual Base *clone() const方法,这将生成一个Base指针,其中包含Derived对象的精确副本,涉及对象的额外副本和额外的克隆...