noob here. Having a doubt while doing an exercise from a book.
The doubt is the following: Why if I use a const std::string * as an argument to a method, the compiler sends me the following error: no matching function for call to ‘BankAccount::define(const char [11], const char [11], int)’ in the client?
If I swap the prototype and definition of the method to accept as an argument a const std::string & (like I did in the constructor) it’s no problem for the compiler.
Client:
// usebacnt.cpp --
#include "BankAccount.h"
#include <iostream>
int main()
{
BankAccount john;
BankAccount mary("Mary Wilkinson", "5000000000"); // balance set to 0 because of default argument
john.display();
mary.display();
john.define("John Smith", "4000000000", 26); // error line
mary.deposit(1000.50);
john.withdraw(25);
john.display();
mary.display();
std::cin.get();
return 0;
}
Class declaration:
// BankAccount.h -- Header file for project Exercise 10.1
#ifndef BANKACCOUNT_H_
#define BANKACCOUNT_H_
#include <string>
class BankAccount
{
private:
std::string fullName;
std::string accountNumber;
double balance;
public:
BankAccount(); // default constructor
BankAccount(const std::string &fN, const std::string &aN, double b = 0.0); // constructor with a default argument
void display() const;
void deposit(double amount);
void withdraw(double amount);
void define(const std::string *pfN, const std::string *paN, double b);
};
#endif
Class implementation:
// methods.cpp -- Compile alongside usebacnt.cpp
#include "BankAccount.h"
#include <iostream>
void BankAccount::display() const
{
using std::cout;
using std::ios_base;
ios_base::fmtflags orig = cout.setf(ios_base::fixed, ios_base::floatfield); // formatting output and saving original
cout.precision(2);
cout << "Full Name: " << fullName << '\n';
cout << "Account Number: " << accountNumber << '\n';
cout << "Balance: " << balance << "\n\n";
cout.setf(orig);
}
void BankAccount::deposit(double amount)
{
if (amount < 0)
{
std::cout << "You can't deposit a negative number! Amount set to zero.";
amount = 0;
}
balance += amount;
}
void BankAccount::withdraw(double amount)
{
if (amount < 0)
{
std::cout << "You can't withdraw a negative number! Amount set to zero.";
amount = 0;
}
if (balance < amount)
{
std::cout << "You can't withdraw more money than you have. Amount set to zero.";
amount = 0;
}
balance -= amount;
}
void BankAccount::define(const std::string *pfN, const std::string *paN, double b)
{
fullName = *fN;
accountNumber = *aN;
balance = b;
}
// constructors
BankAccount::BankAccount() // default constructor
{
fullName = "empty";
accountNumber = "empty";
balance = 0.0;
}
BankAccount::BankAccount(const std::string &fN, const std::string &aN, double b) // constructor with default argument
{
fullName = fN;
accountNumber = aN;
balance = b;
}
Shouldn’t the compiler interpret the literal as a string object (like it does with the reference)? So if I say it’s a pointer it should pass the address of the string (its first element).
Any help?
No. Pointers are not references; smack anyone who tells you that they are.
It all comes down to this:
std::stringis not a string literal. Therefore, when you pass a string literal to a function that takes astd::string, a temporarystd::stringthat holds the contents of the literal must be created. This is done with the conversion constructor ofstd::string.A
const&is allowed to be initialized from a temporary, which allows conversion constructors to work their magic. Aconst*must be a pointer, and you’re not supposed to get pointers to temporaries. Therefore,const*cannot be magically filled in by a temporary created from a conversion constructor.You should use a
const std::string &instead of a pointer. Or astd::stringvalue if you have C++11 move constructors available.