首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++多态shared_ptr

C++多态shared_ptr
EN

Stack Overflow用户
提问于 2021-07-05 10:56:55
回答 2查看 105关注 0票数 0

你帮我修复这段代码,printIt函数exampleA就不用了。我使用了共享指针和reference_wrapper,但是il看起来不太好。

错误结果:

代码语言:javascript
复制
1;2;23;23;23; 

http://cpp.sh/9yqpq

代码语言:javascript
复制
#include <iostream>
#include <vector>
#include <algorithm>
#include <list>
#include <vector>
#include <iostream>
#include <numeric>
#include <random>
#include <functional>
#include <memory>

struct obj{
    int value;
};


class example
{
    public:
  obj _obj;
  
  obj getVal() {return _obj;}
  
   virtual void printIt(){
    
          std::cout << _obj.value<< ";";

}
};

struct exampleA : public example
{
  public:
    
    virtual void printIt() override{
    
          std::cout <<"+++ "<< _obj.value<< "-";

}
};

class Container {
    
        std::vector<std::shared_ptr<example> > input;

public:

void add (const example& a){
    input.emplace_back(std::make_shared<example>(a));
}


std::vector<std::shared_ptr<example> > getInput()
{
    return input;
}
    
};



int main(int argc, const char* argv[])
{

    example one;
    one._obj = obj{1};
    example two;
    two._obj= obj{2};
    exampleA three;
    three._obj =obj{23};
    
    Container cont;

    
        cont.add(one);
         cont.add(two);
          cont.add(three);
          cont.add(three);
          cont.add(three);



    for (std::shared_ptr<example> entry : cont.getInput() )
    {
      example* ref = entry.get();
      ref->printIt();
    }

    return 0;
}

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-07-05 12:13:14

正如注释中所指出的,您可以创建example对象,这些对象是const example& a的副本。对于object3,该a只是对基本部分的引用。这叫“切片”。

一个简单的修复方法是使用模板复制实际的参数类型:

代码语言:javascript
复制
template <typename EX>
void add (EX const& a){
  input.push_back(std::make_shared<EX>(a));
}

现在,当您调用cont.add(three);时,模板参数演绎将推导出EX==exampleAstd::make_shared<ExampleA>将创建一个std::shared_ptr<ExampleA>

然后,这个指针将转换为std::shared_ptr<Example>,以适应向量。但这仍然是指向ExampleA对象的指针!这不是切片。

票数 1
EN

Stack Overflow用户

发布于 2021-07-05 12:28:13

这一行:

代码语言:javascript
复制
    input.emplace_back(std::make_shared<example>(a));

总是创建example类型的新对象,参数a是对example的const引用,因此example的隐式复制构造函数启动并有对象切片。

要正确地修复它,应该将shared_ptr直接传递给add函数:

代码语言:javascript
复制
    void add(std::shared_ptr<example> a)
    {
        input.emplace_back(std::move(a));
    }

以及正确使用此函数的代码。

演示

代码语言:javascript
复制
#include <iostream>
#include <vector>
#include <algorithm>
#include <list>
#include <vector>
#include <iostream>
#include <numeric>
#include <random>
#include <functional>
#include <memory>

struct obj {
    int value;
};

class example {
public:
    obj _obj;

    obj getVal() { return _obj; }

    virtual void printIt()
    {

        std::cout << _obj.value << ";";
    }
};

struct exampleA : public example {
public:
    virtual void printIt() override
    {

        std::cout << "+++ " << _obj.value << "-";
    }
};

class Container {

    std::vector<std::shared_ptr<example> > input;

public:
    void add(std::shared_ptr<example> a)
    {
        input.emplace_back(std::move(a));
    }

    std::vector<std::shared_ptr<example> > getInput()
    {
        return input;
    }
};

int main(int argc, const char* argv[])
{

    auto one = std::make_shared<example>();
    one->_obj = obj{ 1 };
    auto two = std::make_shared<example>();
    two->_obj = obj{ 2 };
    auto three = std::make_shared<exampleA>();;
    three->_obj = obj{ 23 };

    Container cont;

    cont.add(one);
    cont.add(two);
    cont.add(three);
    cont.add(three);
    cont.add(three);

    for (std::shared_ptr<example> entry : cont.getInput()) {
        example* ref = entry.get();
        ref->printIt();
    }

    return 0;
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68254941

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档