【问题标题】:Return pointer to derived class from base class从基类返回指向派生类的指针
【发布时间】:2022-01-03 02:54:58
【问题描述】:

如果以下可能,我想现在。

我有一个名为A 的模板类,它继承自一个名为Base 的类。 在Base 中,我设置了一个write() 函数,为每个派生类重写。

我正在创建一个向量来存储 Base 对象的引用作为打印机 (dataBase)。

我想知道是否可以检索我将其引用传递给dataBaseA 对象的引用。

我有以下代码:

#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;
}

最好的问候

【问题讨论】:

    标签: c++ c++11


    【解决方案1】:
    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
    }
    

    注意:返回引用时,需要返回对有效对象的引用。您不能合法地返回 nullptr 来表示失败,所以我们改为抛出。

    用法:

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

    如果你

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

    将找到两个,但类型不匹配且无法返回 A&lt;int&gt; &amp;。会抛出异常。

    如果你

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

    将找不到 foo 并且无法返回 A&lt;int&gt; &amp;。会抛出异常。

    注意:使用dynamic_cast 通常意味着基类接口没有被充分定义以形成一个好的基类。请参阅Liskov Substitution Principle 进行很好的测试,看看继承是否是在这里使用的好选择。

    Documentation for std::find_if

    Documentation for dynamic_cast

    【讨论】:

    • 您好,非常感谢您的回复。做dynamic_cast_ 是一种安全的方法,对吗?我将更改您的函数以包含模板类型(针对不同类型的A
    • @ManuelOliveira dynamic_cast 与 C++ 一样安全,但通常最好根本不需要它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-06-16
    • 1970-01-01
    • 1970-01-01
    • 2016-02-19
    • 1970-01-01
    • 1970-01-01
    • 2020-02-11
    相关资源
    最近更新 更多