1

I'm using g++ on Debian 8.2 Jessie.

I'm learning about classes in C++. I think I understand the basics, but not fully how to instantiate class objects with header files.

Here's Movie.h:

#ifndef MOVIE_H
#define MOVIE_H

#include <string>
#include <iostream>

class Movie
{
private:
    std::string     m_title;
    int             m_releaseYear;
    std::string     m_description;
public:
    Movie(std::string &title, int releaseYear, std::string &description);
    ~Movie()
    {
        std::cout << "\nDestructor called\n";
    }

    void        setMovieInfo(std::string &title, int releaseYear, std::string &description);

    std::string getTitle();
    int         getReleaseYear();
    std::string getDescription();
    void        printInfo();
};

#endif

Then there's Movie.cpp:

#include "Movie.h"

// Movie constructor
Movie::Movie(std::string &title, int releaseYear, std::string &description)
{
    setMovieInfo(std::string &title, int releaseYear, std::string &description);
}

// Movie mem function
void Movie::setMovieInfo(const std::string &title, const int releaseYear, const std::string &description)
{
    m_title=            title;
    m_releaseYear=      releaseYear;
    m_description=      description;
}

std::string Movie::getTitle()
{
    return m_title;
}

int Movie::getReleaseYear()
{
    return m_releaseYear;
}

std::string Movie::getDescription()
{
    return m_description;
}

void Movie::printInfo()
{
    std::cout << "Title: " << m_title << '\n';
    std::cout << "Year: " << m_releaseYear << '\n';
    std::cout << "Description" << m_description << '\n';
}

And main.cpp:

#include "Movie.h"

int main(){
    std::string     title;
    int             releaseYear;
    std::string     description;

    title=          "Blade Runner";
    releaseYear=    1982;
    description=    "Harrison Ford's character hunts a group of runaway four-year-olds.";

    Movie bladeRunner(title, releaseYear, description);
    bladeRunner.printInfo();

    return 0;
}

I ran g++ -Wall Movie.cpp main.cpp -o main.sh && ./main.sh, but got this output:

Movie.cpp: In constructor ‘Movie::Movie(std::string&, int, std::string&)’:
Movie.cpp:6:27: error: expected primary-expression before ‘&’ token
  setMovieInfo(std::string &title, int releaseYear, std::string &description);
                           ^
Movie.cpp:6:35: error: expected primary-expression before ‘int’
  setMovieInfo(std::string &title, int releaseYear, std::string &description);
                                   ^
Movie.cpp:6:64: error: expected primary-expression before ‘&’ token
  setMovieInfo(std::string &title, int releaseYear, std::string &description);
                                                                ^
Movie.cpp: At global scope:
Movie.cpp:10:6: error: prototype for ‘void Movie::setMovieInfo(const string&, int, const string&)’ does not match any in class ‘Movie’
 void Movie::setMovieInfo(const std::string &title, const int releaseYear, const std::string &description)
      ^
In file included from Movie.cpp:1:0:
Movie.h:20:8: error: candidate is: void Movie::setMovieInfo(std::string&, int, std::string&)
  void  setMovieInfo(std::string &title, int releaseYear, std::string &description);
        ^
Username
  • 3,463
  • 11
  • 68
  • 111
  • May I ask: Why are `Movie::getDescription` and `Movie::printInfo` not defined in `Movie.cpp`? – swinefish Jan 29 '16 at 06:48
  • @swinefish Typo. I'll update it – Username Jan 29 '16 at 06:49
  • Did you make any changes in file other than `main.cpp`? That kind of error often means that the signature in `Movies.cpp` and `Movies.h` do not match – swinefish Jan 29 '16 at 06:56
  • @swinefish The latest version of all three files is now in my question. As far as I can tell, I changed only `main.cpp` – Username Jan 29 '16 at 06:59
  • 2
    The signatures for the declaration and definition of `Movie::setMovieInfo` do not match. – Niall Jan 29 '16 at 06:59
  • 2
    You need to compile `Movie.cpp` also, `g++ Movie.cpp main.cpp -o main` – J.J. Hakala Jan 29 '16 at 07:00
  • 1
    As @Niall points out, in `Movies.h` you have `Movie(std::string title, int releaseYear, std::string description)` (no reference params) while in `Movies.cpp` you have `Movie::Movie(std::string &title, int releaseYear, std::string &description)` (reference params) – swinefish Jan 29 '16 at 07:01
  • 1
    Also, when compiling it's often a good idea to set warnings: `g++ -Wall *.cpp` – swinefish Jan 29 '16 at 07:03
  • 1
    The call to `setMovieInfo` in the constructor should simply be `setMovieInfo(title, releaseYear, description);` – Niall Jan 29 '16 at 07:14
  • @Niall Along with that, removing the `const` from each parameter of `Movie::setMovieInfo()` got the program working. Why does leaving in the `const` result in the same error? – Username Jan 29 '16 at 07:22
  • 1
    Given the function signatures `void fn(const int&)` and `void fn(int&)`, the compiler is able to differentiate them based on the `const`, they are not the same function signatures. So in the class definition you declare the `setMovieInfo` with a signature, when you define it in the cpp file, you give it another signature - this is not allowed, the signatures need to be the same. – Niall Jan 29 '16 at 07:28
  • 1
    You mentioned in one of the edits that you are new to C++, consider getting a good book on it. There is a nice list of them here, http://stackoverflow.com/q/388242/3747990 – Niall Jan 29 '16 at 07:30
  • Nice, thanks for that great resource – Username Jan 29 '16 at 07:32

4 Answers4

1

Reference parameters to functions can initially be a little confusing. While you define a function with

void foo(int& i){}

When you call the function, you do not need to pass a reference. So you would call

foo(x);

rather than

foo(&x);

It can initially be confusing. In your case, simply call

Movie bladeRunner(title, releaseYear, description);

Also, it's worth noting that in your code there is no reason to have the parameters to the constructor be reference parameters. It does reduce memory usage a little, but that really shouldn't be a concern when you're first trying to get your code working. So Movie(std::string title, int releaseYear, std::string description) would be fine.

swinefish
  • 559
  • 6
  • 22
1

The call to setMovieInfo in the constructor should simply be setMovieInfo(title, releaseYear, description);. As it was originally written it is one return type away from being a function declaration.

The signatures for the declaration and definition of Movie::setMovieInfo do not match, the const needs to be removed from the one, or added to the to the other.

Given the function signatures void fn(const int&) and void fn(int&), the compiler is able to differentiate them based on the const, they are not the same function signatures. So in the class definition you declare the setMovieInfo with a signature, when you define it in the cpp file, you give it another signature - this is not allowed, the signatures need to be the same.

Niall
  • 30,036
  • 10
  • 99
  • 142
1

The constructor has three parameters, reference to string, int and another reference to string. As the parameters for the string are references, you can either pass a pointer or the variable in the object instantiation.

For example, a reference can only be

int a;
int &b = a;

You have written something like

int &b = &a;

which is unacceptable.

You can either use two of the below while you instantiate the object

Movie bladeRunner(title, releaseYear, description);

or create a pointer for title and description and pass the pointer.

This is because only a pointer or a variable can be passed to a reference. Here, the constructor stores your parameters as reference to a reference for title and description. I see the same mistake in the function call of setMovieInfo inside constructor.

Also in your definition of constructor, you are calling setMovieInfo. You need not mention the types in the parameters of setMovieInfoas they are already declared in the constructor's parameters. There is also another problem. For the function declaration in Movie.h forsetMovieInfo you have not used any const. Please remove the const in the function definition in Movie.cpp.

Correct these errors and your program will run fine.

Kiran C K
  • 67
  • 7
0

From all the suggestions, I've come up with this working code.

Movie.h:

#ifndef MOVIE_H
#define MOVIE_H

#include <string>
#include <iostream>

class Movie
{
private:
    std::string     m_title;
    int             m_releaseYear;
    std::string     m_description;
public:
    Movie(std::string &title, int releaseYear, std::string &description);
    ~Movie()
    {
        std::cout << "\nDestructor called\n";
    }

    void        setMovieInfo(std::string &title, int releaseYear, std::string &description);

    std::string getTitle();
    int         getReleaseYear();
    std::string getDescription();
    void        printInfo();
};

#endif

Movie.cpp:

#include "Movie.h"

// Movie constructor
Movie::Movie(std::string &title, int releaseYear, std::string &description)
{
    setMovieInfo(title, releaseYear, description);
}

// Movie mem function
void Movie::setMovieInfo(std::string &title, int releaseYear, std::string &description)
{
    m_title=            title;
    m_releaseYear=      releaseYear;
    m_description=      description;
}

std::string Movie::getTitle()
{
    return m_title;
}

int Movie::getReleaseYear()
{
    return m_releaseYear;
}

std::string Movie::getDescription()
{
    return m_description;
}

void Movie::printInfo()
{
    std::cout << "Title: " << m_title << '\n';
    std::cout << "Year: " << m_releaseYear << '\n';
    std::cout << "Description: " << m_description << '\n';
}

main.cpp:

#include "Movie.h"

int main(){
    std::string     title;
    int             releaseYear;
    std::string     description;

    title=          "Blade Runner";
    releaseYear=    1982;
    description=    "Harrison Ford's character hunts a group of runaway four-year-olds.";

    Movie bladeRunner(title, releaseYear, description);
    bladeRunner.printInfo();

    return 0;
}
Username
  • 3,463
  • 11
  • 68
  • 111