基类类型的指针忘记了原始对象类型

时间:2012-06-11 12:02:52

标签: c++ class pointers abstract-class

我有一个指向对象的指针向量,这些对象派生自同一个基类。问题是在调用函数时(但不是方法)忘记了原始对象的类型。

class Cat{
    //base class
public:
    virtual void growl() = 0;
};

class HouseCat : public Cat{
    //derived class
public:
    void growl(){};
};

class AlleyCat : public Cat{
    //derived class
public:
    void growl(){};
};

void function(HouseCat& a){};
void function(AlleyCat& a){};

int main(){
    vector<Cat*> cats;
    cats.push_back(new HouseCat);
    cats.push_back(new AlleyCat);
    function(*(cats[0])); //error: cannot convert parameter 1 from 'Cat' to 'HouseCat &'
    (cats[0])->growl(); //this works though

}

有解决方法吗?

3 个答案:

答案 0 :(得分:4)

  • 将另一个虚拟函数添加到Cat为(add virtual destructor as well):

    class Cat{
       //base class
        ~virtual Cat() {}  //add a virtual destructor as well
         virtual void growl() = 0;
         virtual void call_function() = 0;    
    };
    

    并将其实施为:

    class HouseCat : public Cat{
       //derived class
       virtual void growl(){};
       virtual void call_function() {  function(*this); }
    };
    

    然后你可以这样写:

    cats[0]->call_function();
    

    最终会调用function()的适当重载。

  • 或者只是在类层次结构中将function实现为虚拟成员函数。

答案 1 :(得分:3)

您可以拥有dynamic_cast(我假设您遗漏了virtualgrowl是虚拟的)。

或者您可以将function作为参数Cat&,IMO是最干净的方式。

答案 2 :(得分:1)

每只HouseCat都是Cat,但每只Cat都不是HouseCat。因此,如果您打算学习多态(从您的代码中看起来如此),请记住,允许转换为基类指针/引用,从基类指针/引用到子类的转换并不容易。您必须明确使用dynamic_cast。

但是,除此之外,您的代码还有许多其他问题。方法growl应该声明为virtual,你应该为它指定一个返回类型,你不能从外面调用私有成员函数((cats [0]) - &gt; growl()不会编译)。