【问题标题】:Trying to set up a class thru .h and .cpp files -- why do I get these errors?尝试通过 .h 和 .cpp 文件设置类 - 为什么会出现这些错误?
【发布时间】:2016-01-29 06:42:51
【问题描述】:

我在 Debian 8.2 Jessie 上使用 g++

我正在学习 C++ 中的类。我想我了解基础知识,但不完全了解如何使用头文件实例化类对象。

这里是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(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';
}

还有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;
}

我跑了g++ -Wall Movie.cpp main.cpp -o main.sh &amp;&amp; ./main.sh,但得到了这个输出:

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);
        ^

【问题讨论】:

  • Movie::setMovieInfo 的声明和定义的签名不匹配。
  • 你还需要编译Movie.cppg++ Movie.cpp main.cpp -o main
  • 正如@Niall 指出的那样,在Movies.h 中有Movie(std::string title, int releaseYear, std::string description)(无参考参数),而在Movies.cpp 中有Movie::Movie(std::string &amp;title, int releaseYear, std::string &amp;description)(参考参数)
  • 另外,在编译时设置警告通常是个好主意:g++ -Wall *.cpp
  • 在构造函数中对setMovieInfo的调用应该是setMovieInfo(title, releaseYear, description);

标签: c++ class pointers reference


【解决方案1】:

函数的引用参数最初可能会有点混乱。当你用

定义一个函数时
void foo(int& i){}

调用函数时,不需要传递引用。所以你会打电话

foo(x);

而不是

foo(&x);

最初可能会令人困惑。在您的情况下,只需调用

Movie bladeRunner(title, releaseYear, description);

另外,值得注意的是,在您的代码中,没有理由让构造函数的参数成为引用参数。它确实会稍微减少内存使用量,但是当您第一次尝试让代码正常工作时,这真的不应该是一个问题。所以Movie(std::string title, int releaseYear, std::string description) 就可以了。

【讨论】:

    【解决方案2】:

    在构造函数中对setMovieInfo 的调用应该只是setMovieInfo(title, releaseYear, description);。正如最初编写的那样,它是一种返回类型,而不是函数声明。

    Movie::setMovieInfo 的声明和定义的签名不匹配,const 需要从一个中删除,或添加到另一个。

    给定函数签名void fn(const int&amp;)void fn(int&amp;),编译器能够根据 const 区分它们,它们不是相同的函数签名。所以在类定义中你声明了带有签名的 setMovieInfo,当你在 cpp 文件中定义它时,你给它另一个签名 - 这是不允许的,签名需要相同。

    【讨论】:

      【解决方案3】:

      构造函数有三个参数,对字符串的引用,int 和对字符串的另一个引用。由于字符串的参数是引用,您可以在对象实例化中传递指针或变量。

      例如一个引用只能是

      int a;
      int &b = a;
      

      你写过类似的东西

      int &b = &a;
      

      这是不可接受的。

      您可以在实例化对象时使用以下两种方法

      Movie bladeRunner(title, releaseYear, description);
      

      或者为标题和描述创建一个指针并传递指针。

      这是因为只能将指针或变量传递给引用。在这里,构造函数将您的参数存储为对标题和描述的引用的引用。我在构造函数内部setMovieInfo的函数调用中看到了同样的错误。

      同样在你的构造函数定义中,你调用了setMovieInfo。你不需要在setMovieInfo的参数中提及类型,因为它们已经在构造函数的参数中声明了。还有另一个问题。对于 Movie.h forsetMovieInfo 中的函数声明,您没有使用任何 const。请删除 Movie.cpp 中函数定义中的 const。

      纠正这些错误,你的程序就会运行良好。

      【讨论】:

        【解决方案4】:

        根据所有建议,我想出了这个工作代码。

        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;
        }
        

        【讨论】:

          猜你喜欢
          • 2019-09-17
          • 1970-01-01
          • 2018-01-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-01-21
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多