4

EDIT

Ok, I've done a bit of reading again for a few hours and I think I finally understand c++ OOP a bit better (at least the basics). I decided to rewrite the entire program and code a bit at a time and test more. I think i narrowed the errors i bit more this time.

NamedStorm.h

#include <string>
#include <iostream>

#ifndef NAMEDSTORM_H_INCLUDED
#define NAMEDSTORM_H_INCLUDED

// NEVER use using namespce in header, use std instead.

class NamedStorm{
private:
    std::string stormName;
    std::string stormCategory;
    double maxWindSpeed;
    double stormPressure;
    static int stormCount;
public:

    // Constructor
    NamedStorm(std::string, double, std::string, double);
    NamedStorm(std::string);

    // Destructor
    ~NamedStorm();

    // Get functions
    int getStormCount();
    double getStormPressure();
    double getWindSpeed();
    std::string getStormCategory();
    std::string getName();

    // Set functions
    static void displayOutput();
    static void sortByNames();
    static void sortByWindSpeed();
    static void getAverageWindSpeed();
    static void getAverageStormPressure();
};

#endif // NAMEDSTORM_H_INCLUDED

NamedStorm.cpp

// CPP => Function definition
#include <string>

#include "NamedStorm.h"

using namespace std;

// Defining static variables
int NamedStorm::stormCount = 0;

// Constructor definition
NamedStorm::NamedStorm(std::string sName, double wSpeed, std::string sCat, double sPress){
    stormName = sName;
    windSpeed = wSpeed;
    stormCategory = sCat;
    stormPressure = sPress;
    stormCount++;
}

NamedStorm::NamedStorm(std::string sName){
    stormName = sName;
    stormCount++;
}

// Destructor definition
NamedStorm::~NamedStorm(){}

// Get (Accessor) function definition
int NamedStorm::getStormCount(){
    return stormCount;
}

double NamedStorm::getStormPressure(){
    return stormPressure;
}

string NamedStorm::getStormCategory(){
    return stormCategory;
}

string NamedStorm::getName(){
    return stormName;
}

// Set (Mutator) function definition
void NamedStorm::displayOutput(){}
void NamedStorm::sortByNames(){}
void NamedStorm::getAverageStormPressure(){}
void NamedStorm::getAverageWindSpeed(){}
void NamedStorm::getWindSpeed(){}

main.cpp

#include <iostream>
#include <string>

#include "NamedStorm.h"

using namespace std;

NamedStorm storm[5]; // Error occurs here

int main(){
   // NamedStorm Chris("Chris", 70.0, "T.S", 990.0); 
   // storm[0] = Chris;
    return 0;
}
Tee-Man
  • 67
  • 2
  • 2
  • 5
  • 2
    This `NamedStorm(){};` is not only a declaration, but also a definition. Typo? – dyp Jul 23 '13 at 18:35
  • 4
    One of your constructors is defined twice, one not at all, and please **never** use `using namespace blah;` in a header. – chris Jul 23 '13 at 18:35
  • what do you use to run it - make sure your files are all linked correctly and in the correct order. @DyP it's possible he wants an empty default constructor for some reason. But yes it's defined twice – Eiyrioü von Kauyf Jul 23 '13 at 18:35
  • You should really refrain from `using namespace std`, especially in header files. – juanchopanza Jul 23 '13 at 18:37
  • 4
    Code like this is unlikely to help you understand C++. Quite a bit of it is still basically Java code, just written with a strange syntax that happens to be accepted by a C++ compiler. – Jerry Coffin Jul 23 '13 at 18:40
  • 1
    Your `displayOutput` function has a bug. Use `std::array`, which knows its size, and you can initialize the objects in one go with either array, just like in Java. – chris Jul 23 '13 at 18:47
  • Elaborating on chris' comment on `displayOutput`: Lots of your functions take something like `NamedStorm storm[]` as a parameter. This decays in C++ to `NamedStorm* storm`, such that `sizeof(storm)` is the size of a pointer. Even it it were an array, `sizeof` would yield the *size in bytes*, not the number of elements. – dyp Jul 23 '13 at 18:57
  • Can you try to remove the '{}' brackets from the default constructor declaration so it is not also a definition? Because now a defitinition in .cpp file is invalid (there is no reference to it's declaration). – tomi.lee.jones Jul 23 '13 at 19:02

1 Answers1

4

1. Remove constructor definition

In your header file (NamedStorm.h) you have defined the default constructor of NamedStorm:

NamedStorm(){};

But what you really wanted is just the constructor declaration:

NamedStorm();

The difference between definition and declaration is that the declaration only tells the compiler that there is some function (for example: NamedStorm constructor), whereas the definition provides the full body of this function.

Note that, if you specify only the declaration for your function, and forget to make the definition, you will get the undefined reference linker error.

Further reading: http://www.cprogramming.com/declare_vs_define.html

2. Correct the second constructor

NamedStorm::NamedStorm(string sName, double wSpeed, string sName, double sPress)

This can't work, because you try to pass two arguments with the same name. I guess you wanted to name the second one sCat, since you use such variable in the constructor definition. Correct version:

NamedStorm::NamedStorm(string sName, double wSpeed, string sCat, double sPress)

3. The operator<<

If you read the first section, then you should know what's wrong with the operator<< by now. You provided only the declaration, not the definition.

You can fill it like this:

std::ostream& operator<<(ostream& out, NamedStorm& namedStorm)
{
    out << namedStorm.getName();
    return out;
}

Note that the declaration is also changed - the function now takes NamedStorm& instead of const NamedStorm&, because the getName method is not declared as const. You can read about const methods here.

4. Define static clas variables

Every static variable you declare in your class (only int stormCount in your case) have to be defined. Put this line into your NamedStorm.cpp file:

int NamedStorm::stormCount = 0;

After applying these changes your code should work fine. However, there are still many language nuances that you could read about to improve your code. Some of them are:

1. Passing function arguments as values vs const references

Good read here: Is it better in C++ to pass by value or pass by constant reference?

2. Functions returning object copies vs const references

This question also has a nice answer on SO: Is it more efficient to return a const reference

3. Be careful with "using namespace"

Again, SO: Why is "using namespace std" considered bad practice?

If you really want to use it, never use it in the header file, because it will affect all files that include it.

Community
  • 1
  • 1
podkova
  • 1,019
  • 7
  • 16
  • +1 Useful, but incomplete. The "accessors" taking a `NamedStorm param[]` still contain bugs and/or are error prone (assuming an array size of 5). – dyp Jul 23 '13 at 22:30
  • I decided to start to whole code over again, your solutions help A LOT, but still the code has errors I need to fix – Tee-Man Jul 24 '13 at 19:10
  • @Tee-Man: could you be more specific? There should be no compiler/linker errors if you followed the steps above. – podkova Jul 24 '13 at 19:24
  • Sorry about that, I already solved that problem, not its a "not matching function to constructor" error. – Tee-Man Jul 24 '13 at 19:35