简体   繁体   English

从基础 class 返回指向派生 class 的指针

[英]Return pointer to derived class from base class

I would like to now if the following is possible.如果以下是可能的,我现在想。

I have a templated class called A which inherits from a class called Base .我有一个名为A的模板化 class ,它继承自名为Base的 class 。 In Base I set a write() function to be rewritten for every derived class.Base中,我设置了一个write() function,为每个派生的 class 重写。

I am creating a vector to store the references of the Base objects to be printer latter ( dataBase ).我正在创建一个向量来将Base对象的引用存储为打印机后者( dataBase )。

I would like to know if it is possible to retrieve the reference of the A object whose reference I passed to dataBase .我想知道是否可以检索我传递给dataBaseA object 的引用。

I have the following code:我有以下代码:

#include <iostream>
#include <string>
#include <array>
#include <vector>

class Base
{
    public:
        Base(std::string name):name_(name){}
        virtual ~Base(){}
        virtual void write()=0;

    const std::string& name() const
    {
        return name_;
    }
    
    private:
        std::string name_;
};

template< typename T>
class A : public Base
{
    public:
        A(std::string name):Base(name),name2_(name + "test"){}
        ~A(){}

        void write();

        std::string name2_;

};

template< typename T>
void A<T>::write()
{
    std::cout <<  name2_ << std::endl;
}


int main()
{
        
    A<int> one("one");
    A<double> two("two");
    A<std::array<double,4>> three("three");

    std::vector<Base*> dataBase;
    dataBase.push_back(&one);
    dataBase.push_back(&two);
    dataBase.push_back(&three);

    for(auto i : dataBase)
    {
        i->write();
    }

    A<int>& getOne = lookup("one"); // this is what I want to create
    getOne.name2_  = "worked";

    for(auto i : dataBase)
    {
        i->write();
    }

    return 0;
}

Best Regards此致

A<int>& lookup(std::vector<Base*> & dataBase, // need to provide database
               const std::string & seeking)
{
    // find a match
    auto found = std::find_if(dataBase.begin(),
                              dataBase.end(),
                              [seeking](Base * item)
                              {
                                return item->name() == seeking;
                              });
    if (found != dataBase.end())
    { // found it
        // convert to A<int>
        A<int> * temp = dynamic_cast<A<int>*>(*found);
        if (temp) // dynamic_cast returns nullptr on failure.
        { // successful conversion
            return *temp; // return it.
        }
        throw std::runtime_error("wrong type"); // What we found isn't the desired type
    }
    throw std::runtime_error("not found"); // Couldn't find a match
}

Note: when returning a reference, you need to return a reference to a valid object.注意:返回引用时,需要返回对有效 object 的引用。 You can't legally return a nullptr to signal failure, so instead we throw.你不能合法地返回一个nullptr来表示失败,所以我们抛出。

Usage:用法:

A<int>& getOne = lookup(dataBase, "one");
getOne.name2_  = "worked";

If you如果你

A<int>& getTwo = lookup(dataBase, "two");
getTwo.name2_  = "worked";

two will be found, but the type will not match and an A<int> & can't be returned.将找到两个,但类型将不匹配并且A<int> &无法返回。 An exception will be thrown.将抛出异常。

If you如果你

A<int>& getFoo = lookup(dataBase, "foo");
getFoo.name2_  = "worked";

foo will not be be found and an A<int> & can't be returned.将找不到 foo 并且无法返回A<int> & An exception will be thrown.将抛出异常。

Note: using a dynamic_cast often means the base class interface is not sufficiently defined to make for a good base class.注意:使用dynamic_cast通常意味着基础 class 接口没有被充分定义以形成良好的基础 class。 See the Liskov Substitution Principle for a good test to see whether nor not inheritance is a good choice to use here.请参阅Liskov Substitution Principle进行很好的测试,看看 inheritance 是否是一个不错的选择。

Documentation for std::find_if std::find_if的文档

Documentation for dynamic_cast dynamic_cast的文档

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM