0

I am attempting to make a class in c++ called to store values for a number of parameters that are organized as member variables of class 'Planet' and class 'Satellite', which I want to initialize with a reference to an instance of 'Planet'. Here I provide an example where I have a 'PlanetCatalog' class with member variables 'Planet neptune' and a 'Satellite triton'.

class Planet {
    public:

    double a;

    Planet() {}

    void setParams(  const double a_) {
        a = a_;
    }
};


class Satellite {
    public:

    double b;

    Planet & planet;
    Satellite( Planet & planet_):planet(planet_) { }

    void setParams(const double b_) {
        b = b_;
    }
}; 

class PlanetCatalog {

    public:

    Planet neptune;
    Satellite triton(neptune);

    void setAll() {
        neptune.setParams(1.);
        triton.setParams(2.);
    }

};

However, upon compiling I encounter the error.

error: unknown type name 'neptune' 
    Satellite triton(neptune);

Is it possible to have the Planet and Satellite stored as variables of the same class as I have done here. If not, could someone suggest a better way of organizing this functionality in c++?

Sean Wahl
  • 19
  • 1

2 Answers2

2

Use of parentheses for in-class initialization makes compiler treat triton as a non-static member function declaration with neptune being type of the first argument, you should use list-initialization syntax instead:

Satellite triton{neptune};

Note that there is actually no need to define PlanetCatalog constructor for this.

user7860670
  • 35,849
  • 4
  • 58
  • 84
1

What happened?

class PlanetCatalog {
public:
   ...
   Planet neptune;
   Satellite triton(neptune); //<-- Compiler sees this as a non-static member-function declaration
   ...

Because of the context of that statement, the compiler sees it as a non-static member-function declaration and tries to find such type named neptune within the relevant namespace(s); It issues an error since it can't find it.


Option 1: You can define a constructor that initializes triton for you in its member-initialization-list

class PlanetCatalog {
public:
   ...
   Planet neptune;
   Satellite triton;

   PlanetCatalog() : triton(neptune) {}
   ...

Note: using this option, the order of your class data members matters, because the order initialization of data members is defined by their order of declaration in the class, not by the order of initialization in the member-initialization-list


Option 2: Another straightforward solution will be to use copy-initialization

Satellite triton = neptune;

Option 3: or list-initialization

Satellite triton{neptune};

Options 2 and 3 are preferable because it forces the declaration order implicitly.

WhiZTiM
  • 21,207
  • 4
  • 43
  • 68
  • I was not familiar with list-initialization, but it looks like what I want. However if I just replace the line I had with 'triton(neptune)' to 'triton{neptune}'. I encounter the following error: 'error: function definition does not declare parameters'. In the documentation it seems like the example cases are using to initialize it with the same class ( i.e. planetA{planetB} and not SatelliteA{planetB} ). Should this work for my case? I am not sure what I am missing. – Sean Wahl Nov 09 '18 at 21:50
  • Are you using C++11? ... If you aren't using a veey recent compiler, you may need to add `-std=c++11` flag in the command line invocation of your compiler; or IDE, build file, whatever... You can try more recent standards like `-std=c++14` or `-std=c++17` if your compiler supports it – WhiZTiM Nov 10 '18 at 06:47