关于c ++:基类类型的指针忘记了原始对象类型

Pointer of base class type forgets original object type

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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

}

有解决办法吗?


  • Cat添加另一个虚拟函数as(也添加虚拟析构函数):

    1
    2
    3
    4
    5
    6
    class Cat{
       //base class
        ~virtual Cat() {}  //add a virtual destructor as well
         virtual void growl() = 0;
         virtual void call_function() = 0;    
    };

    并按以下方式实施:

    1
    2
    3
    4
    5
    class HouseCat : public Cat{
       //derived class
       virtual void growl(){};
       virtual void call_function() {  function(*this); }
    };

    然后你可以写下:

    1
    cats[0]->call_function();

    最终将调用适当的function()过载。

  • 或者简单地将function实现为类层次结构中的虚拟成员函数。


你可以有一个dynamic_cast(我假设你省略了virtualgrowl是虚拟的)。

或者可以让function作为参数a Cat&,imo是最干净的方法。


家猫都是猫,但不是家猫。因此,如果您打算学习多态性(从代码中,看起来是这样的),请记住,允许强制转换为基类指针/引用,从基类指针/引用强制转换为子类并不容易。您必须显式地使用动态u cast。

但是,您的代码还有许多其他问题。方法growl应声明为virtual,应为其指定返回类型,不能从外部调用私有成员函数((cats[0])->growl()将不编译)。