Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

'this' argument has type const but function is not marked const

Okay so I'm a bit of a noob at C++ and in my second assignment I am required to make classes with public and private arguments etc, etc. Basically the mutator functions won't work because apparently they're not of type const?

This is the header file with the class:

class Customer {

private:
    string PhoneNumber_;
    string Name_;
    string Address_;

public:
    string get_PhoneNumber() const {return PhoneNumber_;} // Accessor
    const void set_PhoneNumber(unsigned x) {PhoneNumber_ = x;} // Mutator

    string get_Name() const {return Name_;}
    const void set_Name(unsigned x) {Name_ = x;}

    string get_Address() const {return Address_;}
    const void set_Address(unsigned x)  {Address_ = x;}
};

// declare the CreateCustomer function prototype with default values
Customer* CreateCustomer(const string& id = BLANK, const string& name = BLANK, const string& address = BLANK);

Customer* CreateCustomer(const string& id, const string& name, const string& address) {
    Customer* temp = new Customer();

    temp->get_PhoneNumber() = id; // Due to the Accessors and Mutators PhoneNumber, Name and Address are now functions
    temp->get_Name() = name;
    temp->get_Address() = address;

    return temp;
}

And this is the error I get in the main.cpp file:

cout << "\n\nDear ";
    cout << Charge[0].Holder.set_Name() << " (" << Charge[0].Holder.set_PhoneNumber() << ")";  //  DisplayCustomer(customer) ;

    cout << ",\n" << Charge[0].Holder.set_Address() << "\n\n"

Basically, the exact error message is:

Member function 'set_Name' not viable: 'this' argument has type 'const Customer', but function is not type const

It happens with set_PhoneNumber and set_Address as well. Any help would be greatly appreciated! Thanks!

UPDATE: I got it working. Thanks everyone for helping me out!

like image 390
Liam George Avatar asked Sep 11 '15 09:09

Liam George


People also ask

What is const function in C++?

Declaring a member function with the const keyword specifies that the function is a "read-only" function that doesn't modify the object for which it's called. A constant member function can't modify any non-static data members or call any member functions that aren't constant.

What is const after function name?

A function becomes const when the const keyword is used in the function's declaration. The idea of const functions is not to allow them to modify the object on which they are called. It is recommended the practice to make as many functions const as possible so that accidental changes to objects are avoided.

What is a const method?

The const means that the method promises not to alter any members of the class. You'd be able to execute the object's members that are so marked, even if the object itself were marked const : const foobar fb; fb.


3 Answers

If you want to set a value, use the set method. get Methods are only to obtain variables, not to set the inner variables of a class (If they are defined the way you did).

The correct usage is:

Customer* CreateCustomer(const string& id, const string& name, const string& address) {
    Customer* temp = new Customer();

    temp->set_PhoneNumber( id );
    temp->set_Name( name );
    temp->set_Address( address );

    return temp;
}

Also, you have to alter the interface of your methods:

class Customer {

private:
    string PhoneNumber_;
    string Name_;
    string Address_;

public:
    string get_PhoneNumber() const {return PhoneNumber_;} // Accessor
    void set_PhoneNumber(const string& x) {PhoneNumber_ = x;} // Mutator

    string get_Name() const {return Name_;}
    void set_Name(const string& x) {Name_ = x;}

    string get_Address() const {return Address_;}
    void set_Address(const string& x)  {Address_ = x;}
};

Since you want to set strings and not numbers.

Using const string& as function arguments is better than string to not copy the string when passing it as an argument. Since it is a const reference, you don't have to fear the function could manipulate the input.

like image 107
Gombat Avatar answered Oct 11 '22 18:10

Gombat


Ehm. I think you should use get and set in reverse way... In CreateCustomer you should use set functions and when print Customer to stream - you should use get functions. And set functions should receives string, not unsigned.

And so, it will be better to use constructor, instead of set functions and then will be only get functions.

like image 25
ForEveR Avatar answered Oct 11 '22 17:10

ForEveR


  1. You should use std:: in the class declaration. See Why is “using namespace std;” considered bad practice? on the question why.

  2. Your set_ methods take unsigned arguments. You cannot assign an unsigned to a string like PhoneNumber_ = x;. The arguments need to be strings.

You'd need to change your members like

std::string get_PhoneNumber() const { return PhoneNumber_; } // Accessor
const void set_PhoneNumber(std::string const & x) { PhoneNumber_ = x; } // Mutator
  1. When you write temp->get_PhoneNumber() = id; your intention is clearly to set the value for PhoneNumber_, so why do you use the get_ method? Just use the appropriate set_ method and write temp->set_PhoneNumber(id);.

  2. Generally avoid pointers in C++. If you're really in need of a pointer use a smart pointer like std::unique_ptr or std::shared_ptr (if and only if you are required to use a plain pointer: use one).

  3. A 'blank' default value for a std::string is an empty string like

    std::string const & id = std::string{} Appears clearer to me.

  4. To create an object of type Customer with blank/empty member strings you do not need to do more than Customer customer_object; since there is an implicitly declared default constructor which uses the std::string default constructor which results in an empty strign anyway.

  5. Usually a constructor is used to create an object depending on some arguments values.

You could easily write one that takes all required values and can be used as a default constructo anyway by adding something along the lines of

Customer(const std::string& id = std::string{}, 
  const std::string& name = std::string{}, 
  const std::string& address = std::string{})
  : PhoneNumber_(id), Name_(name), Address_(address)
{ }

to your class. See another C++ Class Initialization List example.

See another C++ Class Initialization List example.

  1. For the sake of encapsulation you usually want to avoid using 'direct' getters and setters revealing your data structure.
like image 1
Pixelchemist Avatar answered Oct 11 '22 18:10

Pixelchemist