Inheritance breaking my code?

So I'm working on a school project that has me building and controlling a navel fleet using GNUPlot. So far I've gotten everything to work perfectly, with the sole exception of inheritance. Part of the project is to create a subclass called Submarine that will inherit all the properties of the basic ship, but with the inclusion of being able to have a positive Z axis and a full 360 degree range of movement around the lead ship. But every time I even try to build the subclass (both by hand and using the code blocks class builder), I get a whole host of errors. Ranging from as small as undefined references to ship::ship, to as large as it literally erasing all 200 lines of code from my main.cpp replacing it with a single line saying ELF STX S0H S0H

Something else weird is I get this error
/tmp/ccQQZReq.o:(.rodata._ZTI3sub[_ZTI3sub]+0x18)||undefined reference to `typeinfo for ship'|

but I have no idea what that .o file is, or what typeinfo is.

Below is my ship header file and the header of my sub.

Ship.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
  #ifndef SHIP_H
#define SHIP_H
#include <iostream>
#include <cmath>
#include <random>
#include <ctime>
#include <string>
#include <fstream>
using namespace std;


class ship
{
public:
    ship();
    ship(std::string t, double ba, double r, bool ac);
    virtual ~ship();
/////////////////////////////////////////////////////////
    void moveLead(double angle);
    void follow(double angle, double x, double y, bool lowf);
////////////////////////////////////////////////////////
    void setSpeed(double x)
    {
        this->speed = x;
    }
    double getSpeed()
    {
        return this->speed;
    }
    double getMaxSpeed()
    {
        return this->maxSpeed;
    }
    ////////////////////////////////////////////////////
    void setFuel (double x)
    {
        this->fuel = x;
    }
    double getFuel()
    {
        return this->fuel;
    }
    /////////////////////////////////////////////////////////
    void setBearing (double x)
    {
        this -> bearing = x;
    }
    double getBearing() {return this->bearing;}
    /////////////////////////////////////////////////////////
    void setlocation (double x, double y, double z)
    {
        this->X=x;
        this->Y=y;
        this->Z=z;
    }
    std::string getType(){return type;}
    void setRf(); ///set all ships temp varaibles

    void display()
    {
        cout << this->X << " " << this->Y << " " << this->bearing - 2 << endl;
    }
    ///These getters will mostly be for getting the fuel ship location for refueling
    double getX() {return this->X;}
    double getY() {return this->Y;}
    double getZ() {return this->Z;}
 /////////////////////////////////////////////////////////////////

protected:

    double X, Y, Z; /// ship location in X and Y plane
    double fuel = 100; /// current fuel in the ship
    double bearing, range; ///relative bearing
    double bowangle; ///angle from the lead ship
    double deltar = .05;
    double speed;
    double maxSpeed;
    std::string type;
    bool aircraft; ///true for airwings and rotary wing (aka Lamps)
    ///bool refuel;///  if true -> message guide
    int ID;


private:
    double PI = 3.14156;


};

#endif // SHIP_H 


sub.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#ifndef SUB_H
#define SUB_H

#include "ship.h"


class sub : protected ship
{
    public:
        sub();
    protected:
    private:
};

#endif // SUB_H


Any help is greatly appreciated, this is literally the last piece of this project I need to do. I'm just not sure why it's breaking all of a sudden.
Last edited on
I stripped out your header files and ran the program in one file and it worked fine
#include "ship.h"
Are you sure your header file is actually saved as ship.h or does it have another name?
I'm quite certain. The header file is also included in my main.cpp as ship.h, and so long as there is no sub inherited class, the program compiles and runs perfectly.
You have not defined ship::~ship().

You can explicitly default it:
virtual ~ship() = default;

The linker error you're getting:
/tmp/ccQQZReq.o:(.rodata._ZTI3sub[_ZTI3sub]+0x18)||undefined reference to `typeinfo for ship'

Arises in a temporary object file generated as input to the linker.

The problem is a missing reference to your base class's associated type_info object, which G++ emits along with the dispatch table (for code compiled with -frtti, the default), in order to support dynamic_cast<> and friends.

The manual indicates the type_info object and the virtual table are emitted in the translation unit where the first virtual method in the function is defined (or every TU if the symbol is inline). Since it can't find the missing definition, the linker complains.
https://gcc.gnu.org/onlinedocs/gcc/Vague-Linkage.html

In the case that your missing definition is not the "key method" (see the link), you'll get a usual "unresolved external symbol" error, which is maybe clearer than this special case.
Last edited on
Also, it seems you haven't defined ship::ship() , just like the destructor, one can default it.

Nor is ship::ship(std::string t, double ba, double r, bool ac); defined.

Make sure that all of the constructors initialise all of the member variables. Preferably with a member initialization list.
http://en.cppreference.com/w/cpp/language/initializer_list

Consider splitting your code, with the class declaration in the header file, and the member function definitions in a cpp file. This is better than putting all your functions definitions inline, like you have.

Const correctness: The get functions should be marked const , they don't change the value of any member variable.

If you split your code to header files and cpp files, then in the cpp file you can have the parameters of your functions const as well:

1
2
3
4
5
6
7
8
9
ship::ship(const std::string t, 
                const double ba,  
                const double r, 
                const bool ac) 
: //colon introduces member initialization list
// initialize members here as example link shown above
{
// probably not much to do here, unless to test and  throw exception for invalid data
}


Note there is no const parameters in the class declaration, because that is misleading for the user. They might be mistaken in thinking they have to make them all const before calling the function.

Why do you have protected inheritance? Are you sure on what that does?

One should not have protected member data either, it is just as bad as having public member data.

PI should not be a private member of this class, the only things that have access to it are the member functions. One can put constants like this into their own header file, then include that header file wherever it is needed:

1
2
3
4
5
6
// MathsConstants.hpp
#pragma once // not standard, but has wide support. Can have both this and header guards.
#include <cmath>

constexpr PI = std::acos(-1.0); // need C++11 for constexpr


There might already be an M_PI already defined in <cmath>, but this is unfortunately not standard.

IMO, there is no need for the use of this in your functions.

Instead of having member variables X,Y, Z consider having a member variable of type Point.

Try to have more meaningful names for your variables. Well written code with good names should tell a story of what is happening without too many comments. Here is a comical example of what I mean:
http://www.cplusplus.com/forum/lounge/176684/#msg872881

With double values, I like to always put digits before and after the decimal point, as in : 100.0 and 0.05 not 100 and .05 . It reinforces the idea of the value being a double, and can promote the results of expressions to double.
Thank you all for the wonderful advice. It's late at the moment so I will start working on piecing some of it all together tomorrow. That being said though TheIdeaMan, I do actually have my functions in the constructor defined in the ship.cpp, or atleast I think I do? In my cpp I do correctly use the input values to set them in construction. Unless I'm doing something wrong there. I suppose I'll include that CPP just in case. I just didn't include that because I wasn't sure those particular definitions would have anything to do with why sub wasn't working. Also I guess it's a habit I picked up from my professor to define my setters and getters in the header file. Also the excessive comments, that's more of a reminder for me, I sometmes have trouble remembering certain calculations so I just comment to make sure I don't lose myself. Anyway I'll look into setting the default destructor in the morning.

Ship.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#include "ship.h"

ship::ship(std::string t, double ba, double r, bool ac)
{
    type = t;
    bowangle = ba * PI;
    range = r;
    aircraft = ac;//ctor

}

void ship::setRf()
{
    //this->fx = this -> X;   ///Save current locations
    //this->fy = this -> Y;
    //this->fbearing = 200;
}

void ship::moveLead(double angle)
{
    //cout<< this -> fuel << endl;
    ///get our fuel calculations set up
    double f=0.0; /// fuel percentage used in who numbers
    double c1 = 0.000556; ///factors that effect our fuel usage
    double c2 = -0.000699;
        f=100*(c1*this->speed*this->speed + (c2*this->speed))/2.0; ///fuel percentage calculation
        if(f<2.0)
        {
            f=2.0; ///Garuntee atleast 2% is used
        }
        f = f/100; ///change the percentage into a decimal
    //cout << f << endl;
    f = this->fuel*f; ///Take the percentage of our current fuel stock
    //cout << f << endl;
    f = this->fuel-f; ///take the amount calculated and subtract it from our main ship
    this->setFuel(f); ///set our fuel to the new amount
    //cout<< this -> fuel << endl;
//////////////////////////////////////////////////////////////////

    //normal_distribution<double> bdist (0, 5.0/2.0); ///bearing distribution
    double dx, dy;
    double dz = 0;
    //double theta = 0.0; ///course correction variable

    double alpha = 0.0; /// course correction angle


    dx = this->speed*cos(angle); ///movement directions and length
    dy = this->speed*sin(angle);

    dx = dx + this->getX(); /// add the movement lengths to our current positions
    dy = dy + this->getY();

    this->setlocation(dx, dy, dz);
}

void ship::follow(double angle, double leadX, double leadY, bool lowf)
{
    default_random_engine gen(time(NULL)); ///Random Number Generator
    normal_distribution<double> bdist(0,5.0/2.0); ///Bearing Distribution
    normal_distribution<double> rdist(0,deltar*range/2); ///Range Distribution
    double tempX, tempY;
    double dbearing = angle + bdist(gen);///bearing variation
    double drange = this->range + rdist(gen); ///range variation
    ///This calculation will assume each time that the bearing and range were meant to be the same as the lead,
    /// and varied after acquiring that exact match

    if (lowf == true) {drange = 200;} ///for use in the refueling calculations
    this->X = (cos(this->bowangle+dbearing)*drange) + leadX;
    this->Y = (sin(this->bowangle+dbearing)*drange) + leadY;
    //cout << this-> X << " " << this->Y << endl;
    //cout << leadX << " " << leadY << endl;
}

ship::~ship()
{
    //dtor
}
Last edited on
> I stripped out your header files and ran the program in one file and it worked fine
> and so long as there is no sub inherited class, the program compiles and runs perfectly.
¿what program? I don't see a main()
¿did you even try to instantiate a ship?

you've got a lot of member functions without a body (definition).


> Note there is no const parameters in the class declaration, because that is
> misleading for the user. They might be mistaken in thinking they have to make
> them all const before calling the function.
¿are you serious?


Edit:
> I suppose I'll include that CPP just in case.
> I just didn't include that because I wasn't sure those particular definitions
> would have anything to do with why sub wasn't working.
here's a tip, you have no idea what's relevant to your problem.
so simply post all that's necessary to reproduce your issue.


you are still missing ship default constructor, sub default constructor and `main()'
Last edited on
ne555 wrote:
¿are you serious?


Yes, I learnt this from JLBorges when he made this post:

http://www.cplusplus.com/forum/beginner/207694/#msg979801

I also read that somewhere on ISO CPP FAQ.

Miles Hikari wrote:
Also the excessive comments, that's more of a reminder for me, I sometmes have trouble remembering certain calculations so I just comment to make sure I don't lose myself.


I wasn't saying you had excessive comments, it is a good idea to put comments for formulae if they are complicated. I was talking about the names for your variables. In this code fragment, I don't know what any of the parameters mean, until I read the body of the function :

1
2
3
4
5
6
7
8
ship::ship(std::string t, double ba, double r, bool ac)
{
    type = t;
    bowangle = ba * PI;
    range = r;
    aircraft = ac;//ctor

}


I like to name the parameters after the class member names with "Arg" appended. Perhaps "Arg" is not the best name, but I find it short and fairly obvious :+) - you could use "Param" or something else if you want. Here it is with the member initialization list:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
ship::ship(const std::string& typeArg,  // pass std::string by reference
                          const double bowangleArg,  // BowAngleAsDegreesArg ?
                          const double rangeArg, 
                          const bool aircraftArg,
             // other parameters here, so all members are initialised
)
     : 
type (typeArg), 
bowangle (bowangleArg),
range (rangeArg),
aircraft (aircraftArg),
 //  other member variables here

{
// nothing to do here
    type = t;
    bowangle = ba * PI; // did you want radians here? 
    range = r;
    aircraft = ac;//ctor

}


I find the use of this-> , over the top here. What advantage do you see?
f=100*(c1*this->speed*this->speed + (c2*this->speed))/2.0; ///fuel percentage calculation

There are other good reasons for using this-> but I don't think this is one of them :+)

Miles Hikari wrote:
In my cpp I do correctly use the input values to set them in construction. Unless I'm doing something wrong there.


If you read the link about member initialization, you will see why - at the moment it is implicitly happening twice.
> I stripped out your header files and ran the program in one file and it worked fine
...
@ne55: "¿what program? I don't see a main() "


I supplied the main() into the code
@TheIdeasMan: I don't see anything about «const is misleading for the user» in JLBorges' post

@gunnerfunner: show your main()
I don't understand what you mean with «stripped out your header files». Provide a complete testcase.
Oh sorry sorry, I didn't include main because it's rather long at the moment (well over 7500 characters and close to 200 lines) and also I didn't think it had a lot of weight as to why the Submarine class wouldn't work. Didn't want to bother everyone with looking at code that wasn't relevant to the problem at hand. I can and will post it if everyone would like, I just recall there being a specific rule against "code dumping", or some people getting in trouble for excessively long code posts.

As for why I'm using This->, it's because I'm altering the stats of each ship in a linked list as built by a pointer. So the pointer builds a new ship and then pushes it into the list, and when altering the ships location all of the ships follow the same algorithm but using their own stats. So I just put it in a loop and moved my iterator down the list, using this-> to access the needed variables.

That and because I've had trouble with pointers for some time so I was challenging myself to use them more, stop being so anxious about using them.

I'll include main in the next post (character limit) and also go implement the default constructors and destructors.


Also on a side not if anyone here has experience with GNUPlot and Splot, but there was another issue I'm having with this exact same program that can be found here: http://www.cplusplus.com/forum/beginner/210748/
Main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#include <list>
#include "ship.h"
///#include "sub.h"

///I could have left the objects alone as regular objects instead of making them pointers, but I wanted to experiment more with pointers,
///Overcome some anxiety I have surrounding them
using namespace std;

int main()
{

    list<ship>::iterator myitr;  ///Set some private variables
    list<ship>fleet;
    ship * sptr; ///ship pointer for making new ships
    /// ship * head; ///Don't lose your head
    fstream fout, fout2;
    string fname, outfile;
    double toTurn; ///how much do you want to turn?
    string decide = "y"; ///do we go again?
    double PI = 3.14156; ///Just in case
    bool lowF = false;
    bool topped = false;
///////////////////////////////////////////////////////
    ///I will hard code the needed ships settings in place, instead of using a creation loop to speed up testing
    sptr = new ship("carrier",0,0, true); ///Head carrier
    fleet.push_back(*sptr);
    sptr = new ship("fuel", 1, 100, false);/// Fuel Ship
    fleet.push_back(*sptr);
    sptr = new ship("ddg", .5, 300, true);/// DDG Lamps
    fleet.push_back(*sptr);
    sptr = new ship("ddg2", 1.5, 300, false);/// DDG no-Lamps
    fleet.push_back(*sptr);
    sptr = new ship("frigate", .75, 300, true);/// Frigate
    fleet.push_back(*sptr);
    sptr = new ship("missle", 1.25, 300, false);/// Missle Cruiser
    fleet.push_back(*sptr);
    sptr = new ship("Sub", 0, 300, false);/// Submarine
    fleet.push_back(*sptr);
////////////////////////////////////////////////////////////////////
    myitr=fleet.begin();                ///Let's set the fleet's base stats
    myitr->setBearing(0);
    myitr->setSpeed(10);
    myitr->setlocation(0,0,0);
///////////////////////////////////////////////////////////////////
    fout2.open("command.txt",ios::out); ///build the command file
    fout2<<"set view (60 , 45, 45)"<<endl;
    fout2 << "set ylabel \"x\"" << endl;
    fout2 << "set ylabel \"y\"" << endl;
    fout2<<"set xrange [-1000:1000]"<<endl;
    fout2<<"set yrange [-1000:1000]"<<endl;
    fout2<<"set zrange [-100:100]"<<endl;
    fout2<<"set mapping cylindrical"<<endl;
    ///fout2<<"set angles radians"<<endl;
    fout2<<"set terminal png"<<endl;
////////////////////////////////////////////////////////////////
    cout << "Starting bearing is 0" << endl;
    int i=0; ///Use this to keep track of file names
    while (decide == "y") ///Begin movement
    {
        double days; ///How many days are we moving?
        double dSpeed; ///Our new speed
        cout << "Captain, should we begin changing course?" << endl
             << "[In whole radians, Pi will be added]" << endl;
        cin >> toTurn;
        cout << "What is our current speed, captain?" << endl;
        cin >> dSpeed;
        myitr->setSpeed(dSpeed);
        cout << "How long should we hold this course, sir?" << endl;
        cin >> days;
        ///cout << "Will our sub change? [Depth, angle change]" << endl;
//////////////////////////////////////////////////////////
        ///Calculate Our bearing
        toTurn = (2 *(PI)) - (toTurn * PI); ///In the navy angles go clockwise instead of counter clockwise.
        toTurn = myitr->getBearing() + toTurn; ///add the change in angle to the current bearing to get our new bearing
///I tried previously to do this in the moveLead function, but it caused a loop of constantly changing my bearing
//////////////////////////////////////////////////////////
        for(int j=0; j<days; j++) /// take our input settings
        {
            double headX; ///Values to hold the leaders position
            double headY; ///tried to use a head pointer but it didn't pan out as I hoped
            //head = fleet.begin();/// give us a pointer to the lead ship at all times
            fname="position_"+to_string(i)+".dat";
            outfile="position_"+to_string(i)+".png";
            cout<<fname<<endl;
            ///we take the string, turn it into a char []
            ///so that we can use it as a filename for output
            fout.open(fname.c_str(),ios::out);
///////////////////////////////////////////////////////////////////////////

            if (lowF == true)
            {
                double fx, fy; ///X and y locations of the fuel ship, as well as bearing
                double fspeed = 13;/// these are used in the main file to avoid having unecisarry variables used in the other ships
                //////////////////////////////////////////////////////////
                myitr->setSpeed(fspeed); ///this bit sets our lead with the refuel speed
                myitr->moveLead(toTurn);///move our lead with new speed
                fout << myitr->getX() << " " << myitr->getY() << " " << myitr->getZ() << endl; 
                headX = myitr->getX();
                headY = myitr->getY();
                myitr->setFuel(100);
                myitr++;
                /////////////////////////////////////////////
                myitr->setSpeed(fspeed); ///Set move our fuel into position
                myitr->follow(toTurn, headX, headY, false); ///follow the leader
                fout << myitr->getX() << " " << myitr->getY() << " " << myitr->getZ() << endl; ///print out
                fx = myitr->getX();
                fy= myitr->getY();
                myitr++;

                //////////////////////////////////////////////////////////
                ///myitr = fleet.begin();
                while (myitr != fleet.end())
                {
                    myitr->setSpeed(fspeed); ///move the rest of the fleet around the fuel ship
                    myitr->follow(toTurn, fx, fy, true); ///follow the leader
                    fout << myitr->getX() << " " << myitr->getY() << " " << myitr->getZ() << endl; ///print out
                    myitr++; ///next boat
                }
                lowF=false;

            }

/////////////////////////////////////////////////////////////////////////////////////////////

            else
            {
                if (myitr->getFuel() <=70) ///If our lead ship is at 70% or less fuel, reduce speed and signal fleet
                {
                    lowF = true;
                    myitr ->setSpeed(13);
                }
                myitr->moveLead(toTurn); ///Move our first ship
                headX = myitr->getX();
                headY = myitr->getY();
                    fout << myitr->getX() << " " << myitr->getY() << " " << myitr->getZ() << endl; ///print out

////////////////////////////////////////////////////////////////////////
                myitr++;
                while (myitr != fleet.end()) ///Begin moving the rest of the fleet
                {
                    myitr->setSpeed(dSpeed); ///Set the speed
                    myitr->follow(toTurn, headX, headY, false); ///follow the leader
                    fout << myitr->getX() << " " << myitr->getY() << " " << myitr->getZ() << endl; ///print out
                    myitr++; ///next boat
                }
            }
            ///test = test+5;
            fout.close();

            fout2<<"set output \'"<<outfile<<"\'"<<endl;
            fout2<<"splot \'"<<fname<<"\' with circles"<<endl;
            ///fout2<<"-1"<<endl;
            i++;
            myitr = fleet.begin();
        }
        cout << "would you like to continue? [y]/[n]" << endl;
        cin >> decide;


    }
    fout2.close();
    system("gnuplot command.txt");
    return 0;
}
Last edited on
Update: So I played around with the constructors and deconstructors and I managed to get everything to work (minus the splot problem mentioned before).

Except the weird thing is that the only way I could get it to work is by making the sub inside of ship.h. sub.cpp works fine so far off on it's own, but I could not seem to get a sub header file to work right. Anytime I tried to implement that it would literally shatter my code, delinking all my .h and .cpp files from main. It was weird.
this build for me, separated files
https://github.com/ne555/ship

> I could have left the objects alone as regular objects instead of making them
> pointers, but I wanted to experiment more with pointers,
> Overcome some anxiety I have surrounding them
fine, a couple of things:
- list<ship>fleet; that's a list of ships, it can only hold ships. It cannot hold submarines, checkout object slicing
- fleet.push_back(*sptr); you are inserting a copy there.
- sptr = new ship("fuel", 1, 100, false); memory leak.
- you don't have a single delete
It compiles now, and it can make the submarine no problem. and as I was hoping it does inherit the properties of the ship class. But I keep getting an error now every time I try to write and use a new function that is exclusive to Submarine.for example I now have this code

ship.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
///Insert everything you see in ship.h above


class submarine : public ship
{
    public:
        submarine();
        submarine(std::string ty, double ra, double d);
        virtual ~submarine();
        void setZ(double setz){ this ->Z = setz;}
        void subAlter(double dive, double angle);
    protected:
    private:
    //double depth;
};


submarine.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include "ship.h"

submarine::submarine()
{
    //ctor
}

submarine::submarine(std::string ty, double ra, double d)
{
    type = ty;
    range= ra;//ctor
    Z = d;
}
submarine::~submarine()
{
    //dtor
}

void submarine::subAlter(double dive, double angle)
{
    this->setZ(this->getZ() + dive);
    if (this->getZ() > 0)
    {this -> setZ(0);}
    if (this->getZ() < -100)
    {this -> setZ(-100);}

    this -> bowangle = this -> bowangle + angle;
}


But when I try to use subAlter in my main.cpp, I get this error.

/home/****/CodeBlocks programs/ship/main.cpp|151|error: ‘class ship’ has no member named ‘subAlter’|

I figured this might be an issue with trying to put a sub into a ship list like ne555 mentioned, so I did a test and just made a submarine that wasn't part of that list, and tried test.subAlter,
only to get this error.

/home/****/CodeBlocks programs/ship/main.cpp|39|error: request for member ‘alterSub’ in ‘test’, which is of non-class type ‘submarine()’|
Last edited on
> But when I try to use subAlter in my main.cpp,
¿use it how?


I'm going to guess.
you've got a conceptual error
ship *foo; `foo' is a pointer to `ship'. It only knows of whatever is inside ship, it knows nothing about derived classes.
So when you do foo->member_function(); you can only call member functions of ship, it doesn't matter if you do foo = new sub;, because for the compiler `foo' is a pointer to `ship'.

If you want to call members of `sub' then you need a `sub' object/pointer/reference.
It looks like you were right ne555, I took the sub out of the list and made it an independent object. The code runs and compiles perfectly now... At least I think. No one has been able to help me with the splot post I made so all of my output still appears really weird when the PNGs are made.

Thank you for all your help everyone!
Some other things:

Consider making more use of functions in main.cpp. At the moment you have about 100 LOC in the outer loop. Your comments show quite well what could be in a function.

Instead of using iterators, consider using a range based for loop when you want to iterate a whole container.

You still seem to have a fetish with this->. I asked, but you still haven't enlightened us as to why you do that :+)

Try to avoid using new and delete at all. The main problem is if something throws an exception, delete is never reached. Investigate smart pointers instead, such as std::unique_ptr. If one uses the STL containers, there is no need for any memory management at all.

With the ship pointers and the problem involving derived classes, investigate polymorphism. That way one can have an interface of virtual functions in the base class, and a container declared as holding pointer to base, but populated with pointer to derived class. The virtual functions in the derived classes are redefined to do the appropriate thing for that class.

Good Luck !!
Thank you for the tip Idea Man, and the thing with This->.... Well to put simply I'm just doing as my teach had shown me, and what some of the tutorials I had looked up said, that I should use This-> for functions. Though maybe I forgot something along the way I went overboard... I'll consider that for the future. Also polymorphism is something I've seen thrown around quite a bit in my research. I hope to research it a bit over the summer when classes let up.
Topic archived. No new replies allowed.