代码选择器在运行时使用继承

时间:2014-04-22 13:08:45

标签: c++ inheritance

有没有办法在容器中插入抽象类?第
有没有办法让基类访问派生类?使用虚函数。
有没有办法使这个示例代码正常工作,控制台 bark
有没有办法让vector容器保留实例而不是引用/指针?

如果我对实例使用引用计数器,那么在std::vector内存储指针只会是安全的,这是我的最后手段。我想念一下吗?

class CAnimal
{
public:
    virtual void soundsLike()
    {
        cout<<"Base function\n";
    }   
};

class CDog: public CAnimal
{
public:
    void soundsLike()
    {
        cout<<"Woof\n";
    }
};

class CZoo
{
public:
    std::vector<CAnimal> animalList;

    void addDog()
    {
        animalList.push_back(CDog());
    }

};

控制台输出基本功能消息:

int main(int argc, char* argv[])
{
    CZoo nationalPark;
    nationalPark.addDog();
    nationalPark.animalList.front().soundsLike(); //Calls the base function.
    return 0;
}

4 个答案:

答案 0 :(得分:2)

  

有没有办法在容器中插入抽象类?

没有。但是您可以插入指向抽象类的指针(最好是智能指针)

  

这个示例代码是否有办法正常工作,控制台可以吠叫?

除非你愿意使用指针:否则,吠叫代码would be sliced off

  

向量容器是否有办法保留实例而不是引用/指针?

您可以在容器中保留指针,但不能保留引用。但是,一旦在类中指向了您分配的对象或指针的整个向量,代码的复杂性就会提高,因为您必须遵循the rule of three

  

如果我对实例使用引用计数器,那么在std::vector内存储指针只会是安全的,这是我的最后手段。我想念一下吗?

是的 - 您似乎缺少std::shared_ptr,它会为您引用计数。您为此付出的小代价是必须使用std::shared_ptr代替CZoo中所有动物的简单指针。

答案 1 :(得分:1)

您可以使用std::unique_ptr

std::vector< std::unique_ptr<CAnimal> > zoo;
zoo.push_back(new CDog());
zoo[0]->soundsLike();

不好吗? unique_ptr将为您处理破坏。

我认为你不能使用参考文献。此外,我认为你现在不能让它“吠叫”。只有“woof”。

答案 2 :(得分:1)

如果你真的想跳过在容器中存储指针,这里有一个实现“假虚拟”机制的解决方案。请注意,这只有在您拥有C ++ 11编译器的情况下才有效。您需要通过辅助函数(caller)调用虚方法,并使用一种方法(我的情况为makeNoice),该方法充当虚拟通过该机制引导所有虚拟调用。

#include <iostream>
#include <vector>
#include <functional>
#include <utility>

// forward declarations of the base class and a helper function
class CAnimal;
void caller(CAnimal* a);

// base class with small extensions
struct CAnimal {
    CAnimal() {  mf = std::bind(caller, this); }
    virtual void soundsLike() { std::cout<<"Base function\n"; }

    // this will act as a virtual function
    void makeNoice() { mf(this); }
    std::function<void (CAnimal*)> mf;
};

// a helper function to call the real virtual function
void caller(CAnimal* a) {a->soundsLike();}

// the actual animals
struct CDog: public CAnimal {
    virtual void soundsLike() { std::cout<<"Woof\n"; }
};
struct CCat: public CAnimal {
    virtual void soundsLike() { std::cout<<"Miau\n"; }
};

int main()
{
    CDog dog; 
    CCat cat;

    std::vector<CAnimal> animalList;
    animalList.push_back(dog);
    animalList.push_back(cat);

    // calling the fake virtual
    animalList[0].makeNoice();
    animalList[1].makeNoice();
}

这是关于ideone:http://ideone.com/MRDaZ3

答案 3 :(得分:0)

问题是animalList只是基类CAnimal对象的向量。因此,您的编译器只保留足够的存储空间来保存CAnimal对象。由于虚函数的工作方式,由于查找表的要求,派生的CDog类总是需要比CAnimal类更多的存储空间。

由于您的CDog类没有足够的存储空间,因此对象的CDog部分会被切掉,只剩下对象的CAnimal部分。

使用指针传递对象是优先的,因为对象的地址始终具有相同的存储要求,因此您不会遇到任何对象切片问题。