简体   繁体   English

我想要返回类型指针,但我希望我的函数返回派生类的指针

[英]I want return type pointer but i want my function to return pointer of derive class

Dragon* Dragon::spawn() {
    int x = rand() % 5;
    int y;
    if (!if_locked(x)) //is a function to see if that id is unlocked because i want some dragon to be generated only if you have certain xp so it will call func again until unlocked id is generated
        spawn();
    else
        y = unlocking(m); // Y is generated form 1-5, I have assigned Id to each derive class whosoever id matches Y that pointer will be returned

    if (y == 1) {
        GroundDragon* pt;
        return pt;
        }

    if (y == 2) {
        WaterDragon* st;
        return st;
    }
    if (y == 3) {
        IceDragon*bt;
        return bt;
    }
    if (y == 4) {
        FireDragon* ct;
        return ct;
    }
    if (y == 5) {
        DarkDragon* dark;
        return dark;
    }
}

As you can see im making syntax mistakes i hope someone can guide me正如你所看到的,我犯了语法错误,希望有人能指导我

The return type of function is base class and all the classes in if statement are derive class函数的返回类型是基类,if语句中的所有类都是派生类

so i can later use this function所以我以后可以使用这个功能

 template<class T>
 void spawner(T*) {// I will spawn() fucntion as perimeter at time of call 
   T = new T;
 }

Forgive me if im repaeting question the last time i post it didnt get attention i was expecting so i modifed my code a bit hopeful it is clear now`请原谅我,如果我上次发布问题时我重复了这个问题并没有引起我期待的关注,所以我修改了我的代码,希望现在很清楚了`

int Dragon::unlocking(Mage m) {


if (m.getxp() <= 50 and m.getxp() <= 100) {
    unlock[0] = 1;
    cout << "Congratulation GroundDragon unlocked " << endl;
    return 1;
}

if (m.getxp() > 100 and m.getxp() < 150) {
    unlock[1] = 1;
    cout << "Congratulation WaterDragon unlocked " << endl;
    return 2;
}
if (m.getxp() > 150 and m.getxp() < 175) {
    unlock[2] = 1;
    cout << "Congratulation IceDragon unlocked " << endl;
    return 3;
}

if (m.getxp() > 175 and m.getxp() < 500) {
    unlock[3] = 1;
    cout << "Congratulation FireDragon unlocked " << endl;
    return 4;
}

if (m.getxp() > 500) {
    unlock[4] = 1;
    cout << "Congratulation DarkDragon unlocked " << endl;
    return 5;
}

} }

bool Dragon::if_locked(int x) {
if (unlock[x] == 1) {
    return true;
}
else
    return false;

} }

在此处输入图片说明 *Im not comfortable with smartpointer(i have never used them before but i would love to use them if you show me how to call it main * I used raw pointer but it is still showing me errors please help mw *我对智能指针不满意(我以前从未使用过它们,但如果您告诉我如何将其称为 main,我很乐意使用它们 * 我使用了原始指针,但它仍然显示错误,请帮助 mw

The idea is sound, it's just the execution that failed.这个想法是合理的,只是执​​行失败了。

If you want to have a factory function that will return different objects that will then behave polymorphically, this is perfectly fine, with one important thing - you need to return actual objects.如果你想要一个工厂函数来返回不同的对象,然后这些对象会以多态的方式运行,这完全没问题,但有一件重要的事情——你需要返回实际的对象。

Your factory function has a return type of Dragon* .您的工厂函数的返回类型为Dragon* This means that whatever value you return, it will be a pointer pointing to (some sort of a) Dragon .这意味着无论您返回什么值,它将是一个指向(某种类型的) Dragon的指针。 However, the value of that pointer can point to an object that is actually an instace of FireDragon , IceDragon etc. When you create an instance of such an object, the pointer to such instance can then get converted to the appropriate return type and returned.但是,该指针的值可以指向实际上是FireDragonIceDragon等实例的对象。当您创建此类对象的实例时,指向此类实例的指针可以转换为适当的返回类型并返回。

In your case though, while you're creating temporary objects of type pointer-to-some-sort-of-dragon, you're not actually filling them with instances.但是,在您的情况下,当您创建指向某种龙的指针类型的临时对象时,您实际上并没有用实例填充它们。 They all are created with an unspecified value, and that value is then converted to an unspecified value of type Dragon* , with no way to extract the information which type it was converted from.它们都是用一个未指定的值创建的,然后该值被转换为一个类型为Dragon*的未指定值,无法提取它是从哪种类型转换而来的信息。

So, in order to make it work in a usual fashion, we just need to create a new instance of appropriate type and return it.所以,为了让它以通常的方式工作,我们只需要创建一个适当类型的新实例并返回它。 We don't ever want to return raw pointers from functions when transferring ownership, so std::unique_ptr is a much better alternative:我们不想在转移所有权时从函数返回原始指针,所以std::unique_ptr是一个更好的选择:

std::unique_ptr<Dragon> Dragon::spawn() {
    int x = rand() % 5;

    /* note - this bit of code doesn't make any sense whatsoever
    int y;
    if (!if_locked(x)) //is a different function
        spawn();
    else
        y = unlocking(m); //is also a different function
    */

    // note that `rand() % 5` will produce values 0 through 4.
    switch(x) {
        case 0: return std::make_unique<GroundDragon>();
        case 1: return std::make_unique<WaterDragon>();
        case 2: return std::make_unique<IceDragon>();
        case 3: return std::make_unique<FireDragon>();
        case 4: return std::make_unique<DarkDragon>();
    }
}

Now you don't need the spawner function at all;现在您根本不需要spawner功能; you can directly use the returned value.您可以直接使用返回值。

I think the first important lesson to give is about initializing pointers.我认为第一个重要的教训是关于初始化指针。

The line线
GroundDragon* pt;
declares that there is a pointer to a GroundDragon object, so far so good.声明有一个指向GroundDragon对象的指针,到目前为止GroundDragon顺利。 However, this does not create an object.然而,这并不能创建一个对象。
As an analogy: you created a direction sign that is able to point into the direction of a village, but you do not build an actual village for it to point towards.打个比方:你创建了一个能够指向村庄方向的方向标志,但你没有建造一个实际的村庄来指向它。 And right now, it just points into some random direction.而现在,它只是指向某个随机方向。
Being uninitialized, pt contains a random value, not the address of an existing object of type GroundDragon .由于未初始化, pt包含一个随机值,而不是GroundDragon类型的现有对象的地址。 Doing anything with it will most likely result in bad things (it is undefined behaviour in particular).用它做任何事情很可能会导致不好的事情(特别是未定义的行为)。
In order to initialize it, you would write it like为了初始化它,你可以这样写
GroundDragon* pt = new GroundDragon;
This creates an objects of type GroundDragon on the heap and assigns it's address to pt .这会在堆上创建一个GroundDragon类型的对象,并将其地址分配给pt
Also note that every new needs a delete to keep the memory clean, just to mention this preemptively.还要注意,每个new需要delete以保持内存干净,只是先发制人地提及这一点。

This is very essential knowledge - make sure to understand this.这是非常重要的知识 - 请务必了解这一点。

I wanted to write this in order to show you how to work with raw pointers, as an addition to the answer of Bartek Banachewicz, who did not show the way to initialize raw pointers.我想写这篇文章是为了向您展示如何使用原始指针,作为 Bartek Banachewicz 答案的补充,他没有展示初始化原始指针的方法。 What he then does, using smart pointers, is clearly a way better approach than using raw pointers, though.但是,他使用智能指针所做的事情显然是比使用原始指针更好的方法。 However, I'd say that it is quite important that you are also able to work with raw pointers.但是,我想说您还能够使用原始指针非常重要。 Make sure to be able to do both in the long run, and use smart pointers whenever you can.从长远来看,确保能够做到这两点,并尽可能使用智能指针。

Edit: Now for the other part of your code,编辑:现在对于代码的另一部分,

int x = rand() % 5;
int y;
if (!if_locked(x)) //is a function to see if that id is unlocked because i want some dragon to be generated only if you have certain xp so it will call func again until unlocked id is generated
    spawn();
else
    y = unlocking(m);

First of all, please be aware that calling spawn();首先,请注意调用spawn(); ignores the return value.忽略返回值。 Which means, it has no effect at all.这意味着,它根本没有影响。 What you probably wanted to write is return spawn();你可能想写的是return spawn(); . .
Second, if(!if_locked(x)) seems to me to be the contrary of what it should be.其次, if(!if_locked(x))在我看来与它应该是相反的。 "if not locked" means "if unlocked", and in that case, it should not try it again but instead proceed, right? “如果没有锁定”意味着“如果解锁”,在这种情况下,它不应该再试一次,而是继续,对吧?
And, is the Mage m that you give to unlocking a member of Dragon ?而且,是你用来unlocking Dragon成员的Mage m吗? Sounds like it rather should be a pointer, if you don't especially want a relationship like Dragon owns Mage .听起来更像是一个指针,如果你不是特别想要像Dragon拥有Mage这样的关系。

In any case, I would keep unlocking out of spawn .无论如何,我会继续unlocking spawn A method like spawn says that it is good for spawning.spawn这样的方法说它有利于产卵。 Especially printing that something is unlocked is not something I would intuitively understand a part of the spawning process.尤其是打印某些东西被解锁并不是我直觉上理解的生成过程的一部分。 Also, I would name it differently, as "unlocking" is a status rather than a command.另外,我会以不同的方式命名,因为“解锁”是一种状态而不是命令。 Go like check_for_new_unlocks or something like that, which sounds like a command.check_for_new_unlocks或类似的东西一样,这听起来像一个命令。 And do it separately from spawn .并将其与spawn分开进行。

Also, note that you check for narrow experience intervals - are you sure that it can't happen that an interval is never triggered, as the character might advance over the interval with never calling the method in between?另外,请注意,您检查了狭窄的经验间隔 - 您确定不会发生间隔从未被触发的情况,因为角色可能会在间隔内前进而从不调用其间的方法吗?

Furthermore, I'd call the array that says if something is unlocked differently.此外,我会调用表示某些内容是否以不同方式解锁的数组。 "unlock" sounds like a command. “解锁”听起来像一个命令。 How about "available"? “可用”怎么说?

Also, I find the recursive call of spawn to be less readable as trying out other values for x , but that is opinion.此外,我发现spawn的递归调用在尝试x其他值时可读性较差,但这是意见。 I'd go like我想去

int x = rand() % 5;
while(not available[x])
{
    x = rand() % 5;
}

Maybe this can be done more clever, though, based on the actual mechanics.不过,根据实际机制,也许这可以做得更聪明。 You could create the random variable like int x = rand() % total_available();您可以创建随机变量,如int x = rand() % total_available(); for instance.例如。

Note that a lot of this is somewhat opinion based.请注意,其中很多都是基于意见的。 In this regard, I want to point you towards CodeReview - as soon as your code works correctly, you might want to post it there for people to help you improve it in several different regards.在这方面,我想向您指出CodeReview - 一旦您的代码正常工作,您可能希望将其发布在那里,以便人们帮助您在几个不同方面改进它。

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

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