C++ 运行时使用继承的代码选择器

C++ 运行时使用继承的代码选择器,c++,inheritance,C++,Inheritance,有没有办法在容器中插入抽象类?否。 基类是否有访问派生类的方法?使用虚拟函数。 有没有办法让这个示例代码正常工作并让控制台发出吠声? vector容器是否有办法保存实例而不是引用/指针 只有在使用实例的引用计数器(这是我最后的选择)时,在std::vector中存储指针才是安全的。我错过什么了吗 class CAnimal { public: virtual void soundsLike() { cout<<"Base function\n";

有没有办法在容器中插入抽象类?否。
基类是否有访问派生类的方法?使用虚拟函数。
有没有办法让这个示例代码正常工作并让控制台发出吠声?
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());
    }

};

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

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

有没有一种方法可以让这个示例代码正常工作并让控制台发出声音

除非你愿意带着指针走,否则,你的代码就是吠叫

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

可以在容器中保留指针,但不能保留引用。然而,一旦在类中有一个指向您分配的对象的指针或整个指针向量,代码的复杂性就会增加,因为您必须遵循

只有在使用实例的引用计数器(这是我最后的选择)时,在
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());
    }

};
是-看起来你失踪了,这对你来说并不重要。您为此付出的小代价是必须使用
std::shared_ptr
来代替
CZoo
中所有动物的简单指针


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

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

有没有一种方法可以让这个示例代码正常工作并让控制台发出声音

除非你愿意带着指针走,否则,你的代码就是吠叫

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

可以在容器中保留指针,但不能保留引用。然而,一旦在类中有一个指向您分配的对象的指针或整个指针向量,代码的复杂性就会增加,因为您必须遵循

只有在使用实例的引用计数器(这是我最后的选择)时,在
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());
    }

};
是-看起来你失踪了,这对你来说并不重要。你为此付出的代价很小,那就是必须使用
std::shared_ptr
来代替你可以使用的
CZoo中所有动物的简单指针

std::vectorzoo;
zoo.push_back(新的CDog());
zoo[0]->soundsLike();
坏吗?unique_ptr将为您处理销毁

我认为你不能使用参考资料。我也不认为你能让它“吠叫”目前。只有“汪”声。你可以用

std::vectorzoo;
zoo.push_back(新的CDog());
zoo[0]->soundsLike();
坏吗?unique_ptr将为您处理销毁


我认为你不能使用参考资料。我也不认为你能让它“吠叫”目前。只有“汪汪”声。

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

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


使用指针传递对象是首选的,因为对象的地址总是有相同的存储要求,所以不会遇到任何对象切片问题。

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

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


使用指针传递对象是首选的,因为对象的地址总是有相同的存储要求,所以您不会遇到任何对象切片问题。

如果您真的想跳过在容器中存储指针,下面是一个实现“伪虚拟”机制的解决方案。请注意,只有在拥有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();
}
#包括
#包括
#包括
#包括
//基类和辅助函数的前向声明
犬类;
无效调用方(CAnimal*a);
//具有小扩展的基类
犬结构{
CAnimal(){mf=std::bind(调用者,this);}

virtual void soundsLike(){std::cout如果您真的想跳过在容器中存储指针,下面是一个实现“伪虚拟”机制的解决方案。请注意,只有当您拥有C++11编译器时,这才有效。您需要通过帮助函数(
调用方
)调用虚拟方法,并使用一种方法(
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();
}
#包括
#包括
#包括
#包括
//基类和辅助函数的前向声明
犬类;
空钙