简体   繁体   中英

C++ class error message: no matching function for call

My program is supposed to calculate the surface area and volume of a box. I am to have the following functions: setHeight, setWidth, setLength, getVolume, getSurfaceArea.

When I compile my program I get the following error message:

boxMain.cpp: In function ‘int main()’:
boxMain.cpp:21: error: no matching function for call to 'Box::getVolume(double&, double&, double&)’
Box.hpp:20: note: candidates are: double Box::getVolume()
boxMain.cpp:23: error: no matching function for call to ‘Box::getSurfaceArea(double&, double&, double&)’
Box.hpp:21: note: candidates are: double Box::getSurfaceArea()

Based on my searches on this site, most answers seem to suggest that the default constructor doesn't exit or isn't working. I don't know if that is my issue as well, but I wrote the code for my default constructor according to textbook, so I have trouble figuring out what I did wrong.

The missing lines in my code below are just the descriptions and comments that I removed.

Any help would be appreciated! Thank you all so much in advance.

Here is my .hpp file:

 #include <iostream>
 #ifndef Box_HPP
 #define BOX_HPP

 class Box {

 private:
    double h, w, l;
    double height, width, length;

 public:
    void setHeight(double h);
    void setWidth(double w);
    void setLength(double l);
    double getVolume();
    double getSurfaceArea();
    Box();
 };

Here is my function .cpp file:

 #include <iostream>
 #include <iomanip>
 #include "Box.hpp"

 double height;
 double width;
 double length;

 Box::Box() {
    height = 1.0;
    width = 1.0;
    length = 1.0;
 }

 void setHeight(double h) {
    if(h < 0) {
       std::cout << "Error. Height must be positive."
                 << std::endl;
    }
    else {
    height = h;
    }
 }

 void setWidth(double w) {
    if(w < 0) {
       std:: cout << "Error. Width must be positive."
                  << std::endl;
    }
    else {
    width = w;
    }
 }

 void setLength(double l) {
    if(l < 0) {
       std::cout << "Error.  Length must be positive."
                 << std::endl;
    }
    else {
    length = l;
    }
 }

 double getVolume() {
    return (height * width * length);
 }

 double getSurfaceArea() {
    return (2.0 * length * height + 2.0 * width * height);
 }

Here is my main .cpp file:

 #include <iostream>
 #include <fstream>
 #include "Box.hpp"

 int main() {
     Box box1;
     double h, w, l;

     std::cout << "Enter height" << std::endl;
     std::cin >> h;
     std::cout << "Enter width" << std::endl;
     std::cin >> w;
     std::cout << "Enter length" << std::endl;
     std::cin >> l;

     void setHeight(double h);
     void setWidth (double w);
     void setLength (double l);

     std::cout << "volume: "
          << box1.getVolume(h, w, l) << std::endl;
     std::cout << "surface: "
          << box1.getSurfaceArea(h, w, l) << std::endl;

     return 0;
 }

Box::getVolume is declared as taking no parameters, but in line 21 you call it with 3 arguments:

box1.getVolume(h, w, l)

Use simply box1.getVolume() instead. Similarly for Box::getSurface() .

Also, use Box:: in front of all member function definitions, like void Box::setHeight(double h) {...} , otherwise you end up defining free standing functions and you'll get linker errors since the member functions end up not defined.

vsoftco's answer is mostly correct so I have up voted him, although I feel it would be good to add some more information to the answer to help explain it a bit better as well as help clean up several other issues you have here.

The error you had clearly explains the problem if you look at it. It mentions boxMain.cpp in the function int main() as having the problem. It further gives you the line number and mentions that there is "no matching function" for the "call" and in both instances notes the call as well as the possible candidates, which in this case is the methods without parameters.

with that aside here are some other tips that may help you avoid further frustration:

  1. Prefer forward declarations instead of includes in your header files. In your case you don't need #include <iostream> at all in your box.hpp. The reason is that anything in your header is effectively leaked into any files that include your header. This is mainly to help reduce circular dependancies as well as shorten compile times when making changes. The Pimpl Idiom is an example pattern used with this mantra. I would not recommend using naked pointers, however, instead stick with RAII types such as smart pointers or plain references.

  2. You either didn't paste all of your code or your include guard is wrong. You need a closing #endif in your header.

  3. You should use a convention to name your member variables to avoid conflicts and keep your large .cpp files easier to read. This is a preference more then a rule but it helps. Something like _height , mHeight , _mHeight rather then height . Lower case camel style variable names are common for locals and parameters. It also looks like you really don't need the h,w,l members at all.

  4. You should probably use assert for your error handling so as to optimize it out during release builds. That is of coarse unless you are intending to show the end user the error message. You may also consider using std::cerr instead.

  5. The height , width , length variables in your .cpp are also extraneous and do not do what you think.

  6. You should use an initialization list in your constructor instead of doing the simple work of assigning to variables in the body. There are several special situations as well but this can get you started. ex: Box::Box() : height(1.0), width(1.0), length(1.0){}

  7. The only method in the cpp you fully qualified with Box:: is the constructor. You need to do that with all the methods as well. ex: double Box::getVolume()

  8. You are also not calling the correct methods in your main function (in fact you are not calling methods at all. You are basically forward declaring them.) you should be using an object to invoke the methods. This is why you didn't see a complaint in the error log about missing Box::

There is one major error in your header file that has nothing to do with your class's declaration, but has to do with the header during the pre-compilation stage. Your header guard is not correct as you have first have your #include <iostream> before the guard; this should be after the guard. Second your #ifndef CLASS_NAME does not match your #define CLASS_NAME and you are missing the matching #endif at the bottom of your header file. I will remove the #include <iostream> since it is not needed. The reason I am doing this is because if a user enters a value that is less than or equal to zero it will be set to a default value of 1. So there is no need to print out any error messages for this class.

Your class is close to what you need. There are a few things that would help to improve your class and maybe this will help.

Box.h

#ifndef BOX_H
#define BOX_H

class Box {
private:
    double m_width;
    double m_length;
    double m_height;

    double m_volume;
    double m_surfaceArea;

public:
    Box(); // Default Constructor
    Box( double width, double length, double height );
    // virtual ~Box(); // Default Okay

    void setWidth( double width );
    void setLength( double length );
    void setHeight( double height );

    double getWidth() const; 
    double getLegnth() const;
    double getHeight() const;

    double getVolume() const;
    double getSurfaceArea() const;

private:
    // If You Need Either The Copy Constructor Or The Assignment Operator
    // Remove Them From The Private Section Into The Public Section 
    // Where You May Need To Implement Them Where The Default May Not Be Appropriate
    Box( const Box& c ); // Not Implemented 
    Box& operator=( const Box& c ); // Not Implemented

    void calculateVolume();
    void calculateSurfaceArea();

}; // Box

#endif // BOX_H

Box.cpp

#include "Box.h"

// -------------------------------------------------------------------------
// Box() - Default Box Will Have a 1 x 1 x 1 Dimension
Box::Box() :
m_width( 1.0 ),
m_length( 1.0 ),
m_height( 1.0 ),
m_volume( 0.0 ),
m_surfaceArea( 0.0 ) {
    calculateVolume();
    calculateSuraceArea();
} // Box

// -------------------------------------------------------------------------
// Box() - User Defined Constructor
Box::Box( double width, double length, double height ) :
m_volume( 0.0 ),
m_surfaceArea( 0.0 ) {

    if ( width <= 0 ) {
        m_width = 1.0;
    } else {
        m_width = width;
    }

    if ( length <= 0 ) {
        m_length = 1.0;
    } else {
        m_length = length;
    }

    if ( height <= 0 ) {
        m_height = 1.0;
    } else {
        m_height = height;
    }

    calculateVolume();
    calculateSurfaceArea();

} // Box

// -------------------------------------------------------------------------
// setWidth()
void Box::setWidth( double width ) {
    // First Check To See If Value Passed In Is Same Member Value
    if ( width == m_width ) {
        // Nothing To Do
        return;
    } else if ( width <= 0 ) {
        m_width = 1.0
    } else {
        m_width = width;
    }

    calculateVolume();
    calculateSurfaceArea();

} // setWidth

// -------------------------------------------------------------------------
// setLength()
void Box::setLength( double length ) {
    // First Check To See If Value Passed In Is Same Member Value
    if ( length == m_length ) {
        // Nothing To Do
        return;
    } else if ( length <= 0 ) {
        m_length = 1.0
    } else {
        m_length = length;
    }

    calculateVolume();
    calculateSurfaceArea();

} // setLength

// -------------------------------------------------------------------------
// setHeight()
void Box::setHeight( double height ) {
    // First Check To See If Value Passed In Is Same Member Value
    if ( height == m_height ) {
        // Nothing To Do
        return;
    } else if ( height <= 0 ) {
        m_height = 1.0
    } else {
        m_height = height;
    }

    calculateVolume();
    calculateSurfaceArea();

} // setHeight

// -------------------------------------------------------------------------
// getWidth()
double Box::getWidth() const {
    return m_width;
} // getWidth

// -------------------------------------------------------------------------
// getLength()
double Box::getLength() const {
    return m_length;
} // getLength

// -------------------------------------------------------------------------
// getHeight()
double Box::getHeight() const {
    return m_height;
} // getHeight;

// -------------------------------------------------------------------------
// getVolume()
double Box::getVolume() const {
    return m_volume;
} // getVolume

// -------------------------------------------------------------------------
// getSurfaceArea()
double Box::getSurfaceArea() const {
    return m_surfaceArea;
} // getSurfaceArea

// -------------------------------------------------------------------------
// calculateVolume()
void Box::calculateVolume() {
    m_volume = m_width * m_length * m_height;
} // calculateVolume

// -------------------------------------------------------------------------
// calculateSurfaceArea()
void Box::calculateSurfaceArea {
    m_dSurfaceArea = (m_width  * m_length * 2) + 
                     (m_width  * m_height * 2) +
                     (m_length * m_height * 2);
} // calculateSurfaceArea

With the design of this class the calculations for both the volume and surface area are private to this class only for all they do is an internal calculation that get saves into the classes member variable where there are public access methods available to retrieve them. Also each of the 3 dimensional setters does the same check as both constructors for values that are less than and equal to 0 and if so will default them to 1.

If the value that is passed into any of the setter functions is the same that is already stored the function will do nothing and just return. If the value is greater than 0 and is not equal to what is already saved, it will overwrite the member variable and call both of the private calculate methods to update the volume and surface area.

Now if you want to improve this for better performance then you can declare both calculate methods as inline, move them out of the cpp file and either add them into the header file after your class declaration and before the #endif or you can add an `#include "Box.inl" and just create another header file type with the same name as the class except with the inl extension and cut and paste these two functions in there.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM