-2

I have an assignment for school:

i. Create a classical Guitar object with price $150 and type = “classical”. Set the new price to $100 and display all the information about the Guitar object.

ii. Create an electric Guitar object with price $135 and type = “electric”. Change the price as there is a promotion and display all the information about the Guitar object.

I am trying to solve it on my own, but I am new in C++ and I'm stuck with compiler errors that I can't understand.

Here the class that I have created in my Guitar.h file.

#pragma once
#include<iostream>
#include <string>
#include<sstream>
using namespace std;

class Guitar
{
private:
    string type;
    double price;
public:
    Guitar(string type, double price);
    string getType();
    double getPrice();
    void setPrice(double newPrice);
    void setPrice(bool promotion);
    string toString();
};

This is the class implementation in my Guitar.cpp file

#include "Guitar.h"

Guitar::Guitar(string typeclass, double priceclass)
{
    type = typeclass;
    price = priceclass;
}
string Guitar::getType()
{
    return type;
}
double Guitar::getPrice()
{
    return price;
}
void Guitar::setPrice(double newPriceclass)
{
    price = newPriceclass;
}
void Guitar::setPrice(bool promotion)
{
    if (promotion == true)
        price *= 0.9;
}
string Guitar::toString()
{
    stringstream info;
    info << "Guitar Type: " << type << endl
        << "Price: " << price << endl;
    return info.str();
}

Finally I have my main file GuitarApp.cpp

#include"Guitar.h"

int main()
{
    Guitar guitar1("Classical", 150.0);
    guitar1.setPrice(100) << endl;
    cout << guitar1.toString() << endl;
    Guitar guitar2("Electrical", 135.0);
    guitar2.setPrice(true);
    cout << guitar2.toString() << endl;
}

I have 2 errors:

  1. more than one instance of overloaded function Guitar::setPrice matches the argument list
  2. Guitar::setPrice ambiguous call to overloaded function.

Can someone explain to me the errors and what I should do to get the code compiled?

Edit: After having changed 100 to 100.0, I got 4 more errors:

  1. mismatch in formal parameter list
  2. expression must have integral or unscoped enum type
  3. cannot determine which instance of function template std::endl; is intended
  4. '<<': unable to resolve function overload

All errors are on line 7 of my GuitarApp.cpp which is

guitar1.setprice(100.0)<<endl;

If i were to edit the price of the guitar from 100.0 back to 100, I would get the two error that I initially had.

Christophe
  • 68,716
  • 7
  • 72
  • 138
Kris
  • 35
  • 1
  • 7
  • Change 100 to 100.0. What are the other four errors? – Karsten Koop Nov 27 '16 at 09:15
  • Your compilr certainly tells the line number of the errors; can you complete ? By the way, there's a missing cout now (because you didn't have the endl error before) – Christophe Nov 27 '16 at 10:04
  • @Christophe All of the error is on line 7 of my GuitarApp.cpp which is guitar1.setprice(100.0)< – Kris Nov 27 '16 at 10:10
  • @Kris add cout<< at the beginning of this line – Christophe Nov 27 '16 at 10:11
  • @kris the line 7. If you have no cout the the << will be understood as a shift operator and the endl will not match the requirements of this operator – Christophe Nov 27 '16 at 10:17
  • Got it. I feel so stupid not noticing that. Thanks @Christophe ! – Kris Nov 27 '16 at 10:23
  • @Kris with pleasure. I've edited the question to clarify the problem statement (compiler errors, because readers don't have the time to guess if it's compiling problems or wrong behaviour during the execution). Note that in a header you'd better not use namespaces. Use such statements only in the cpp files (some good advices here: http://www.acodersjourney.com/2016/05/top-10-c-header-file-mistakes-and-how-to-fix-them/) – Christophe Nov 27 '16 at 12:38

2 Answers2

3

The type of the literal 100 is int. Since int is just as easily convertible to bool as it is to double, it's ambiguous which of those functions should be called.

Changing 100 to 100.0 (a double literal) should fix this.

qxz
  • 3,814
  • 1
  • 14
  • 29
  • Yes ! One could even advise for this reason to use another function name for activating the promotion, like promote() or setPromotion() – Christophe Nov 27 '16 at 10:08
  • True, the real solution would be to name the functions better – qxz Nov 28 '16 at 02:06
-1

Normally we did not fix home works here. It is better to ask "Why this line of code did not work" instead of throwing a bunch of homeworks here in the hope to get it made ready from others...

Please also get in mind that your question is "Off topic" because:

Questions seeking debugging help ("why isn't this code working?") must include the desired behavior, a specific problem or error and the shortest code necessary to reproduce it in the question itself. Questions without a clear problem statement are not useful to other readers.

OK, your code have following syntax bugs:

guitar1.setPrice(100.) ; // see the "." behind the number!

You have to methods:

void setPrice(double newPrice);
void setPrice(bool promotion);

And you wrote:

 guitar1.setPrice(100)  

100 is an int and not a double and not a bool. So the compiler can not decide to make from your 100 a bool which has value true or make it a double with value 100.. So simply add a dot to make your value a floating point one which your compiler takes as double.

Next bug:

cout << guitar2.toString() << endl;  // see the "2" behind guitar !

Only a typo...

Some remarks:

Splitting such a class in a header and a source file is bad! The optimizer has no chance to inline the functions.

Using using namespace std; can be bad! It is much better to write std::string and all you need to see from which namespace your definition comes. That makes a bit more work but is much better to read later, especially if you use multiple namespaces from multiple libraries.

Explanation:

It is easy to save typing some characters at a first view. But if you later (re-)use your code in an bigger application where you have to deal with a lot of libraries which may define functions/classes/what ever with the same name as one of the other library do, you start changing your code.

A simple example is to have posix read and istream read in place. Here it is also a good idea to give a '::read' to select the posix one which is not bound to a namespace.

Is it dogmatic to give the hint to not use using namespace? My personal experience is simply that if you use it, you may run into problems if your code is (re-)used later in bigger applications. And for me it is mandatory to write my code as such, which can be (re-)used without problems and or a lot of adoptions/corrections in future.

You have to decide: Save some characters to type today and may run into trouble later or do the job right now.

Maybe for the homeworks code is ok to do so. But I believe it is a good point to talk about the problems which may arise on that kind of code writing.

Klaus
  • 24,205
  • 7
  • 58
  • 113
  • 1
    *"Using `using namespace std;` is bad!"*. Not dogmatically bad. Only in a a way the pollutes the global namespace. There's nothing wrong with doing it in function scope, if the namespace is references a lot. – StoryTeller - Unslander Monica Nov 27 '16 at 09:32
  • @StoryTeller: http://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice – Klaus Nov 27 '16 at 09:36
  • 1
    You are still being dogmatic. You can always disambiguate if you have a name collision. And I suggest you consider what you prefer to read: `v.erase(std::remove(std::begin(v), std::end(v), elem));` or `v.erase(remove(begin(a), end(a), elem));` (Let's disregard ADL for the sake of argument). – StoryTeller - Unslander Monica Nov 27 '16 at 09:39
  • @StoryTeller: I will clarify that a bit, but yes, for me it is "bad practice". But also yes, everybody can do what he/she want, but the price to pay is higher then the savings you may have. – Klaus Nov 27 '16 at 10:11
  • You can't a priori claim a "price". Namespaces are good, we should all use them. But if my 2 line function that uses a single library can be made more readable with a single `using namespace std;` at the first line, you can bet I'd do it. As well as many others. There's no place for dogma in programming. – StoryTeller - Unslander Monica Nov 27 '16 at 10:20