简体   繁体   中英

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

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

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* . This means that whatever value you return, it will be a pointer pointing to (some sort of a) 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.

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.

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<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; 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. 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 . 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 .
Also note that every new needs a delete to keep the memory clean, just to mention this preemptively.

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. 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(); ignores the return value. Which means, it has no effect at all. What you probably wanted to write is return spawn(); .
Second, if(!if_locked(x)) seems to me to be the contrary of what it should be. "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 ? Sounds like it rather should be a pointer, if you don't especially want a relationship like Dragon owns Mage .

In any case, I would keep unlocking out of spawn . A method like spawn says that it is good for spawning. 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. And do it separately from 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. 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(); 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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