需要指导:从抽象基类到派生类的unique_ptr的vector对象

Guidance Needed: Vectors of unique_ptr to dervied classes from an abstract base class

本文关键字:unique ptr 对象 vector 派生 基类 抽象      更新时间:2023-10-16

我正在努力简化我的代码,使其工作得更好,更容易:

这意味着深入研究向量和unique_ptr,我已经读了很多关于它们的好东西。然而,它们对我来说是全新的。这两方面我都读了几页,但还是很难理解。

我现在做的是用传统的方式创建抽象类的对象:

VirtualBaseClass* foo1= new DerviedClass1; 
VirtualBaseClass* foo2= new DerviedClass2;
VirtualBaseClass* foo3= new DerviedClass3;

但是因为我有3个——很可能会有更多——我想让它们之间的切换更容易,因为我要比较每个程序运行的对象的任何组合。

目前,要切换,我只是重命名我想要实例化对象的DerviedClass,这样我就不必用foo3来重命名每个foo1,等等。

VirtualBaseClass* Generic1 = new DerviedClass3;
VirtualBaseClass* Generic2 = new DerviedClass1;

但最终我希望用户告诉程序要比较哪两个对象。因此,一个好的起点似乎是将其作为VirtualBaseClass的数组,但从研究来看,删除数组似乎是痛苦的,因此人们建议使用智能指针和向量。

所以我试着两者都用。对于唯一指针,我使用

unique_ptr<vBaseClass*> foo1(DerviedClass1);
unique_ptr<vBaseClass*> foo2(DerviedClass2);
unique_ptr<vBaseClass*> geneic1 = move(foo1);

然而,从我读到的,我应该做的

unique_ptr<vBaseClass*> foo1(new DerviedClass1);

但是new给出了类型说明符的错误,但是因为没有它就可以工作,所以我认为它没什么。使用move(foo1)时,我得到一个错误,例如重载函数match没有移动,并且编译了一大堆其他错误,例如

unique_ptr<vBaseClass*> champ1 = move(foo1);

错误C3867: 'Controller::foo1':函数调用缺少参数列表;使用'&Controller::foo1'创建一个指向成员的指针错误C2780: '_OutTy *std::move(_InIt,_InIt,_OutTy (&)[_OutSize])':期望3个参数-提供1个

所有这些都是在我的Controller.h文件中完成的。我非常需要指导。我不知道我所做的是否有必要,我需要用向量来表示这个吗?我又该如何开始呢?有更好的方法吗?我如何让用户告诉程序使用哪个对象?对于数组,foo1输入0或者foo2输入1但是对于向量呢?有没有更好的办法?

我的实际代码

#pragma once
#include "stdafx.h"
#include "Skarner.h"
#include "MasterYi.h"
#include "Riven.h"

using namespace std;
class Controller
{
public:
    Controller();
    ~Controller();
    double PCFreq;
    __int64 CounterStart;
    int CounterCheck;
    ofstream out;
    Champion* skarner = new Skarner;//old way of doing it
    //Champion* yi = new MasterYi;//old way of doing it
    //Champion* riven = new Riven;//old way of doing it
    //Champion** champions = new Champion*[200];
    //Champion[0] = new Skarner();
    //unique_ptr<Champion> skarner(Skarner);
    unique_ptr<Champion> yi(new MasterYi);// doesn't work new error
    unique_ptr<Champion*> riven(Riven); //works with or without *
    unique_ptr<Champion*> champ1 = move(riven)//error with move
    vector<unique_ptr<Champion>> pChampions;//vector of pointers to champion
    //unique_ptr<Champion> champ2;
    //Champion *champ1 = dynamic_cast<Champion*>(yi);
    //Champion *champ2 = dynamic_cast<Champion*>(skarner);//not sure what the signficance of this is
//Leaving some methods out 
};

哇,显然你不能只在cpp文件中使用头文件中的"new"。然而,我仍然不确定如何很好地利用它,现在我有它声明在控制器。cpp?我真的希望它是一个成员变量/实例变量。

尝试做这个。在controller.h

shared_ptr<Champion> yi;
shared_ptr<Champion> riven;
shared_ptr<Champion> skarner;
shared_ptr<Champion> champ1;
shared_ptr<Champion> champ2;

和在.cpp中定义它们

Controller::Controller()
{
    PCFreq = 0.0;
    CounterStart = 0;
    out.open("finalStats.txt");
    CounterCheck = 0;
    yi = shared_ptr<Champion> (new MasterYi);
    riven = shared_ptr<Champion>(new Riven);
    skarner = shared_ptr<Champion>(new Skarner);
    champ1 = move(yi);
    champ2 = move(riven);
}

上面的代码现在似乎工作,但我没有看到任何直接的好处。

说明

你的*太多了:

unique_ptr<vBaseClass> foo1(new DerivedClass1);

应该通过分配一个具有动态存储持续时间的新DerivedClass1并将指向它的指针存储在foo1中来实现这一技巧。

提醒一下,只需大声读出类型:foo1具有类型"指向vBaseClass的唯一指针"。

对于评论中的人群

下面显示了原始指针和唯一指针在用法上的区别:

{
    int* a = new int(42);
    unique_ptr<int> b(new int(42));
    std::cout << *a << ", " << *b << "n";
    delete a;
}

没有进一步的差异。你遇到的任何进一步的问题都与另一个问题有关,如果没有进一步的信息,这个问题很难确定。

同样,unique_ptr<Champion*> riven(Riven);是一个函数声明,它指向一个名为riven的函数,返回一个unique_ptr<Champion*>,并接受一个Riven类型的参数。这不会出错的原因是因为它根本没有做你认为它会做的事情。

最后,头文件绝对没有什么特别之处。事实上,c++在解析之前执行文本替换,因此实际的解析器甚至不知道代码来自哪里!

<

业力演示/h3>代码:

struct champ { virtual std::string whoami() = 0; };
struct karma : champ { std::string whoami() override { return "karma"; } };
int main() {
    champ* a = new karma;
    std::unique_ptr<champ> b(new karma);
    std::cout << a->whoami() << ", " << b->whoami() << "n";
}
结果:

karma, karma
证明

unique_ptr<Champion> yi(new MasterYi);// doesn't work new error在编译器看来像一个函数声明,而new在这个上下文中是无效的。

unique_ptr<Champion*> riven(Riven); //works with or without * 看起来像一个函数声明,有或没有*都有效。

unique_ptr<Champion*> champ1 = move(riven)//error with move你不能把一个函数move变成unique_ptr .

我真的很难理解你的问题,但也许你的意思是这样的:

unique_ptr<Champion> yi = new MasterYi;
unique_ptr<Champion> riven = new Riven;
std::vector<std::unique_ptr<Champion> > pChampions = { new Skarner };