beginner questions about class and objects - c++

I'm working on a small program for school that is an intro to using objects. I'm new to class and still trying to wrap my head around it. I'm not really asking how to fix my code, I'm just looking to get a better understanding of things.
In the code below, in my implementation file student.cpp, there is a function called isLessThanByID. It is supposed to compare the current object to the object being passed in. I'm having a hard time understanding what the "current" object is and how the function knows what the current object is. There are two objects s1 and s2. My instructor says assume s1 is the current object and s2 is the passed in object. I asked my instructor how the function knows about s1 if it's not being passed in and she said it's because s1 is an object of class and the function is a class member. This made sense for a minute and then I thought on it more and realized I'm still confused. If s1 doesn't need to be passed in, then why does s2 need to be passed in?
I'm getting an error on that function that says
"error: extra qualification ‘Student::’ on member ‘isLessThanByID’ [-fpermissive] bool Student::isLessThanByID(const Student &s2) const;".
I'm not sure what it means by "extra qualification".
I really appreciate any help in wrapping my head around this! Thank you!
Here's my code:
app.cpp
const double minGpaForHonor = 3.75;
int main()
{
Student s1("G10", 3.9);
Student s2("G20", 3.5);
s1.print();
s2.print();
//write code to test Student::isLessThanByID
s1.isLessThanByID(s2);
if (true)
cout << "s2 is less than s1" << endl;
else
cout << "s1 is less than s2" << endl;
//write code to test Student::qualifyForHonor
s1.qualifyForHonor(minGpaForHonor);
if (true)
cout << "s1 qualifies for honors" << endl;
s2.qualifyForHonor(minGpaForHonor);
if (true)
cout << "s2 qualifies for honors" << endl;
return 0;
}
student.cpp - implementation file
//implement the required 3 functions here
Student::Student(const char initId[], double gpa)
{
//initialize ID
for (int i = 0; i < strlen(initId); i++)
{
id[i] = initId[i];
}
gpa = gpa;
//initialize gpa
}
bool Student::isLessThanByID(const Student &s2) const
{
//compare current student object to passed in object}
if (strcmp(s1.id, s2.id) < 0)
return true;
else
return false;
}
bool Student::qualifyForHonor(double minGpaForHonor) const
{
//return true if gpa is higher than "minGpaForHonor"
if(gpa >= minGpaForHonor)
return true;
}
void Student::print() const
{
cout << id << '\t' << gpa << endl;
}
student.h- header file
#define STUDENT_H
#include <iostream>
#include <cstring>
using namespace std;
class Student
{
public:
Student(const char initId[], double gpa);
bool Student::isLessThanByID(const Student &s2) const;
bool qualifyForHonor(double minGpaForHonor) const;
void print()const;
private:
const static int MAX_CHAR = 100;
char id[MAX_CHAR];
double gpa;
};
#endif

How the function knows about s1 if it's not being passed in?
Each member function has an implicit (hidden) first parameter that passes a pointer to the "current" object (available inside that function as this). Imagine that
bool Student::isLessThanByID(const Student &s2) const
{
return strcmp( /* s1. */ id, s2.id) < 0;
}
is actually something like
bool Student::isLessThanByID(const Student* this, const Student &s2) // not real code
{
return strcmp(this->id, s2.id);
}
Similarly, imagine that the call
s1.isLessThanByID(s2);
is actually
Student::isLessThanByID(&s1, s2); // not real code
Note that there is no s1 inside isLessThanByID available. That object exist outside of the function definition, so, you cannot use it inside. Instead of s1.id just write this->id, or, shortly, just id (which will be interpreted as this->id implicitly in your case).

Related

In the Test Driver cannot get getName function, getStockNo function , or getNoInStock function to output the correct information

In the Test Driver.cpp file, I cannot get the getName, getStockNo, or getNoInStock to output the correct information. The set functions and the get functions for classifications and price work. I do not know how to get char from the getName function. I have attached both the CPP file and the header file. I am only having issues with the Test Driver.cpp file
//Test Driver.cpp
#include <iostream>
#include <fstream>
#include <string>
#include <cctype>
#include <string>
#include "GameRecord.h"
using namespace std;
int main()
{
// Creating the object of the GameRecord class
GameRecord gr1;
// Setting the values in the GameRecord object gr1 as per the given question
gr1.setName("VideoGame");
gr1.setStockNo(200);
gr1.setClassification(10);
gr1.setPrice(250.0);
gr1.setNoInStock(5);
//problem here
char video;
int size = 0;
gr1.getName(&video, size);
cout << "Getting Name: " << video << endl;
//problem here
long stkNo = 0;
gr1.getStockNo();
cout << "Getting Stock Number: " << stkNo << endl;
int classification;
gr1.getClassification(classification);
cout << "Getting Classification: " << classification << endl;
double price;
gr1.getPrice(price);
cout << "Getting Price: $" << price << endl;
//problem here
int NoInStock = 0;
gr1.getNoInStock();
cout << "Getting Number in Stock: " << NoInStock << endl;
// Creating another object of the GameRecord class
GameRecord gr2("VideoGame2", 100, 5, 150.0);
// To print the Gamerecord object values, call the printRecord() function
gr2.printRecord();
}
//GameRecord.cpp file
#include <iostream>
#include <string.h>
#include "GameRecord.h"
using namespace std;
// Default Constructor used to initialize the data members of the class
GameRecord::GameRecord()
{
strcpy_s(m_sName, "");
m_lStockNo = 0;
m_iClassification = 0;
m_dPrice = 0.0;
m_iCount = 0;
}
// Argumented Constructor is used to initializing the data members of the class with the
respective values GameRecord::GameRecord(const char* name, long sn, int cl, double or)
{
strcpy_s(m_sName, sizeof(m_sName), name);
m_lStockNo = sn;
m_iClassification = cl;
m_dPrice = or ;
m_iCount = 1;
}
// Destructor of the class
GameRecord::~GameRecord()
{
}
/* Getter Setter Method of the GameRecord class, Getter method is used to
get the respective values and setter is used to set the values*/
void GameRecord::getName(char* name, int nameSize)
{
strcpy_s(name, nameSize, m_sName);
}
void GameRecord::setName(const char* name)
{
strcpy_s(m_sName, sizeof(m_sName), name);
}
long GameRecord::getStockNo()
{
return m_lStockNo;
}
void GameRecord::setStockNo(long sn)
{
m_lStockNo = sn;
}
void GameRecord::getClassification(int& cl)
{
cl = m_iClassification;
}
void GameRecord::setClassification(int cl)
{
m_iClassification = cl;
}
void GameRecord::getPrice(double& c)
{
c = m_dPrice;
}
void GameRecord::setPrice(double c)
{
m_dPrice = c;
}
int GameRecord::getNoInStock()
{
return m_iCount;
}
void GameRecord::setNoInStock(int count)
{
m_iCount = count;
}
void GameRecord::printRecord()
{
cout << m_sName << " " << m_lStockNo << " " << m_iClassification << " " << m_dPrice << " "
<< m_iCount << endl;
}
//GameRecord.h file
#pragma once
#include <iostream>
#include <string.h>
using namespace std;
class GameRecord
{
private:
char m_sName[128]; // used to store the name of a videogame or videogame system.
long m_lStockNo; // used to store a unique stock number for the videogame or videogame
system int m_iClassification; // used to code specific information about the videogame or
videogame system
.double m_dPrice; // used to store the price of this videogame or videogame system
int m_iCount; // used to store the number of copies of this item currently in the
inventory.
public
: GameRecord(); // constructor set the member variables to the following initial values.
// set the member variables to the values passed into the function and initialize the
m_iCount variable to one(1).GameRecord(const char* name, long sn, int cl, double price);
~GameRecord(); //The destructor shall be an empty, place - holder function.
// copy the member variable m_sName into the character array pointed to by the function argument.
void getName(char* name, int nameSize);
// function will copy the function argument into the member variable m_sName.
void setName(const char* name);
// function shall return the value stored in the member variable m_lStockNo.
long getStockNo();
// function will copy the function argument into the member variable m_lStockNo.
void setStockNo(long sn);
// function will copy the member variable m_iClassification into the interger variable referenced by the function argument.
void getClassification(int& cl);
// function will copy the function argument into the member variable m_iClassification.
void setClassification(int cl);
// function will copy the member variable m_dPrice into the double variable pointed to by the function argument.
void getPrice(double& c);
// function will copy the function argument into the member variable m_dPrice.
void setPrice(double c);
int getNoInStock(); // function shall return the value stored in the member variable
m_iCount.
void
setNoInStock(int count); // function will copy the function argument into the member
variable m_iCount.
void
printRecord(); // shall print to the screen all data found in the record
};
the function getName should be used as
int size=...;
char*name=new char[size];
c.gerName(name,size);
because it works by copying the name to the pointer got in the input

Add string elements to Dynamic Array

Parsing a file and need to add students to a struct vector using an array for student names specific to that course line.
In my course.h file:
struct Course {
std::string name;
int enrollment;
int maxEnrollment;
std::string* students; ///< array of student names
Course(std::string courseName, int maxEnrollmentPermitted);
bool enroll(std::string studentName);
void print(std::ostream& output);
};
In my course.cpp file:
bool Course::enroll(std::string studentName) {
this->students = new std::string[studentName];
if (this->enrollment < this->maxEnrollment) {
this->enrollment++;
return true;
}
else {
return false;
In my source file:
void processEnrollmentRequests(istream& enrollmentRequestsFile, vector<Course>& courses) {
// Read the requests, one at a time, serving each one
string courseName;
enrollmentRequestsFile >> courseName;
while (enrollmentRequestsFile) {
enrollmentRequestsFile >> ws;
string studentName;
getline(enrollmentRequestsFile, studentName);
int pos = search(courses, courseName);
if (pos >= 0) {
// Found a matching course
bool enrolled = courses[pos].enroll(studentName);
if (enrolled) {
cout << studentName << " has enrolled in " << courseName << endl;
}
else {
// course is full
cout << studentName << " cannot enroll in " << courseName << endl;
}
}
else {
// course does not exist
cout << studentName << " cannot enroll in " << courseName << endl;
}
enrollmentRequestsFile >> courseName;
}
}
}
}
I cant seem to add the gathered studentName to the array using this->students = new std::string[studentName]. Getting an error that says must have integral or enumeration type.
new SomeThing[size] is used to declare array. It makes no sense to use a string as the size.
Assuming the size of students is limited to maxEnrollment, you can use this:
if (this->enrollment < this->maxEnrollment) {
this->students[this->enrollment++] = studentName;
return true;
}
else {
return false;
For the sake of completeness, the allocation of students is not the only problem. Given that the code you posted also uses std::vector<Course>, and Course does not follow the rule of 3, using it in a std::vector is highly likely to cause memory corruption, leaks, etc.
Given that you state that students must remain a pointer, the complete fix is to write Course in this manner:
#include <string>
#include <algorithm>
struct Course {
std::string name;
int enrollment;
int maxEnrollment;
std::string* students; ///< array of student names
Course(std::string courseName, int maxEnrollmentPermitted);
bool enroll(std::string studentName);
void print(std::ostream& output);
Course(const Course& rhs);
Course& operator =(const Course& rhs);
~Course();
};
Course::Course(const Course& rhs) : name(rhs.name),
enrollment(rhs.enrollment),
maxEnrollment(rhs.maxEnrollment),
students(new std::string[rhs.maxEnrollment])
{
for (int i = 0; i < maxEnrollment; ++i)
students[i] = rhs.students[i];
}
Course& Course::operator= (const Course& rhs)
{
Course temp(rhs);
std::swap(temp.students, students);
std::swap(temp.maxEnrollment, maxEnrollment);
std::swap(temp.enrollment, enrollment);
std::swap(temp.name, name);
return *this;
}
Course::~Course() { delete [] students; }
Course::Course(std::string courseName, int maxEnrollmentPermitted) :
name(courseName),
enrollment(0),
maxEnrollment(maxEnrollmentPermitted),
students(new std::string[maxEnrollmentPermitted])
{}
Why all of this code? Well, in the code you posted in your question, you are using a std::vector<Course>. The Course class as written could not be safely used in a vector, due to Course having incorrect copy semantics. Thus your error you're getting may have a lot to do with code you stated wasn't yours (the vector<Course>).
The adjustments to Course above now makes Course safe to be used in a vector since the copy semantics (copy constructor, assignment operator, and destructor) have now been implemented to handle the dynamically allocated students member.
Note that absolutely none of this code would be necessary if students were simply a std::vector<std::string> instead of std::string *.
For more reading:
What is the rule of 3?
What is the copy / swap idiom?

Using an enum from a class (C++)

I'm reading a book on C++ and was writing out some code to practice using the interface and implementation of a class. I've searched for solutions to my issue for a while to no avail.
I have a class with an enumeration inside of it. While trying to instantiate an object of that class, I am having trouble accessing the enum types outside of the class. I have tried using Book::Horror, Biblo::Horror, Biblo::Book::Horror, Horror, and even things like Biblo::Book::Genre::Horror. Can't seem to get it to let me access the types of the enum for the instantiation of my object in the main.cpp file.
Any help is appreciated! The more complex uses of C++ are still new to me. Here is my source:
book.h
#include <iostream>
#include <string>
using namespace std;
namespace Biblo{
class Book{
public:
enum Genre{
No_Genre, Horror, Comedy, Romance, Mystery
};
// The rest of this header is working fine I think, just this enum
class Invalid{}; // Used for throwing errors
Book(int n_ISBN, int n_copyrightYear, string n_title, string n_author, Genre n_genre);
Book();
// Accessors (non-modifying)
int getISBN() const { return ISBN; }
int getCopyrightYear() const { return copyrightYear; }
string getTitle() const { return title; }
string getAuthor() const { return author; }
string getGenre() const;
// Mutators
void changeAuthor(string newAuthor);
private:
int ISBN;
int copyrightYear;
string title;
string author;
Genre genre;
}; // End Book
// Helper Functions go here
bool operator==(const Book& a, const Book& b);
bool operator!=(const Book& a, const Book& b);
} // End Biblo
and main.cpp
#include <iostream>
#include "book.h"
using namespace std;
int main()
{
Biblo::Book book(100, 2012, "The Walrus", "The Eggman", Book::Horror); // THIS LINE GIVES ERROR
cout << "ISBN: " << book.getISBN() << endl;
cout << "Copyright: " << book.getCopyrightYear() << endl;
cout << "Title: " << book.getTitle() << endl;
cout << "Author: " << book.getAuthor() << endl;
cout << "Genre: " << book.getGenre() << endl;
return 0;
}
Edit: here is the book.cpp file
#include <iostream>
#include "book.h"
#include <string>
namespace Biblo{
Book::Book(int n_ISBN, int n_copyrightYear, string n_title, string n_author, Genre n_genre)
:ISBN(n_ISBN), copyrightYear(n_copyrightYear), title(n_title), author(n_author), genre(n_genre)
{
// constructor
}
Book::Book()
:ISBN(0), copyrightYear(0), title(""), author(""), genre(Genre::No_Genre)
{
// Default constructor
}
// Accessors
string Book::getGenre() const
{
if (Book.genre == Genre::No_Genre)
return "No Genre!";
if (Book.genre == Genre::Horror)
return "Horror";
if (Book.genre == Genre::Comedy)
return "Comedy";
if (Book.genre == Genre::Romance)
return "Romance";
if (Book.genre == Genre::Mystery)
return "Mystery";
}
// Mutators
void Book::changeAuthor(string newAuthor)
{
author = newAuthor;
}
// Helper Functions
bool operator==(const Book& a, const Book& b)
{
if (a.getISBN() != b.getISBN())
return false;
if (a.getCopyrightYear() != b.getCopyrightYear())
return false;
if (a.getTitle() != b.getTitle())
return false;
if (a.getAuthor() != b.getAuthor())
return false;
if (a.getGenre() != b.getGenre())
return false;
return true;
}
bool operator!=(const Book& a, const Book& b)
{
return !(a==b);
}
} // End Biblo
It seems you tried everything but the thing you needed! The enum is nested inside the Book class which is within the Biblo namespace. The code you are looking for is:
int main()
{
Biblo::Book book(100, 2012, "The Walrus", "The Eggman", Biblo::Book::Horror);
return 0;
}
You need to include the enum class. eg.:
Biblio::Book::Genre::Horror
Bunch of things that are going wrong really.
As others mentioned your enum is stashed one level deeper than you think it is, and your complaint about fixing it then producing an undefined reference is probably because at that point you bump into the fact there's nothing much initialized, and if you got past that you are returning items somewhat poorly when it comes to the enumerator.
If you use the right name space, quickly put in an actual implementation for the constructor, and get the most immediate return for your enum (an int might work) it should work, and probably look like this:
#include <iostream>
#include <string>
using namespace std;
namespace Biblo{
class Book{
public:
enum Genre{
No_Genre, Horror, Comedy, Romance, Mystery
};
// The rest of this header is working fine I think, just this enum
class Invalid{}; // Used for throwing errors
Book(int n_ISBN, int n_copyrightYear, string n_title, string n_author, Genre n_genre);
Book();
// Accessors (non-modifying)
int getISBN() const { return ISBN; }
int getCopyrightYear() const { return copyrightYear; }
string getTitle() const { return title; }
string getAuthor() const { return author; }
int getGenre() const { return genre; }
// Mutators
void changeAuthor(string newAuthor);
private:
int ISBN;
int copyrightYear;
string title;
string author;
Genre genre;
}; // End Book
Book::Book(int n_ISBN, int n_copyrightYear, string n_title, string n_author, Genre n_genre){
ISBN = n_ISBN; copyrightYear = n_copyrightYear; title = n_title; author = n_author;
};
}
using namespace std;
int main()
{
Biblo::Book book(100, 2012, "The Walrus", "The Eggman", Biblo::Book::Horror); // THIS LINE GIVES ERROR
cout << "ISBN: " << book.getISBN() << endl;
cout << "Copyright: " << book.getCopyrightYear() << endl;
cout << "Title: " << book.getTitle() << endl;
cout << "Author: " << book.getAuthor() << endl;
cout << "Genre: " << book.getGenre() << endl;
return 0;
}
Are you sue the book you're following isn't discussing details such as initializer lists or something else for constructors concurrent to, or previous to, the subjects you're looking at?
The code looked somewhat incomplete.
Edited in line here on SO, so bear with the poor formatting and the merged h/cpp look :)

Passing a class object to a list table

I have a struct list, a class castomer. I want to store my castomer to the list. For that I am creating a castomer each time and I strore them to a list table. There are no errors except that the program crashes each time I try to store a castomer into my table.
I have this list and class:
class castomer{
private:
string name;
string lastname;
int number;
double time;
public:
void setAll(string,string,int,double);
int numberR(){return number;}
double timeR(){return time;}
void displayAll();
};
struct node {
castomer person;
struct node *next;
};
This function for adding castomer:
void add(clock_t *start,struct node *table[])
{
*start = clock();
double time=(double)*start;
int i=0;
while(table[i]!=NULL)
{
i++;
}
if(i > 24)
cout << "We are not able to add another castomer becase we are full please wait for ont to go "<<endl;
else{
castomer c1;
cout<<i;
cout<< "Give me the castomers name and lastname :";
string temp1,temp2;
cin>>temp1;
cin>>temp2;
c1.setAll(temp1,temp2,i,time);
table[i]->person=c1;//my program crases here anyone knows why?
}
}
ps: In my main the table[] looks like this struct node * table[25];
struct node* table[25]
This is declaring table to be an array of 25 pointers. You have to allocate memory for each of these pointers which from looking at your code is missing.
After your while-loop, table[i] will be NULL.
table[i]->person = c1; // Your program crashes here because of that.
Using your code as it is, you should do
table[i] = new node;
table[i]->person = c1;
But the code looks very strange, like you want to implement a linked list (the node structure) but are sticking to using arrays for some reason.
If you're aiming for a linked list, you need to rethink a lot of your code.
If you're not, you can lose the node type completely.
Since you are using (or trying to use) C++ I will make mention of a few things you can do to improve your code and make your own life easier.
In C++ you can define constructors for initializing objects.
Your function setAll is a bad practice. You don't really want to change all data of a person after you have created. You just want to initialize the data at creation time. Well use constructors.
You don't need pointers
For what you want to do you don't need complicate the code using pointers you could pass the arguments by reference.
You are using C++, use STL
Specifically vector I guarantee it, will help you.
Use cout << for displaying yuor object
you could add a friend ostream& operator<< function to your class in order to be able to write code like:
Customer a;
cout << a << endl;
A complete example:
#include <iostream>
#include <vector>
#include <ctime>
#include <string>
using namespace std;
class Customer
{
public:
Customer(){} // default constructor.
Customer(string pname, string plastname): name(pname), lastname(plastname)
{
id = ++idgen; // Set an id number.
time = (double)clock(); // initialize time.
}
int getId() {return id;} // former numberR().
double getTime() {return time;} // former timeR().
friend ostream& operator<<(ostream &out, Customer obj)
{out << obj.name << " " << obj.lastname << ". " << "Id: " << obj.id << " Time: " << obj.time;}
private:
static int idgen; // static values are a good way for keep some sort of id.
int id; // former member: number.
double time; // Why don't use clock_t directly?
string name, lastname;
};
int Customer::idgen = 0; // Initialize static variable.
int main()
{
int const MAX_NUMBER_PERSONS = 2;
std::vector<Customer> customer_list;
string name, lastname;
while (customer_list.size() < MAX_NUMBER_PERSONS)
{
cout << "Give me the castomers name and lastname <name> <lastname>:";
cin >> name >> lastname;
customer_list.push_back(Customer(name, lastname));
}
for (auto &x: customer_list) // If you're learnign C++ its a good moment for search
{ // for c++11 doc.
cout << x << endl;
}
return 0;
}

Compiler not interpreting well pointers to string literals as arguments for a method

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?
Shouldn't the compiler interpret the literal as a string object (like it does with the reference)?
No. Pointers are not references; smack anyone who tells you that they are.
It all comes down to this: std::string is not a string literal. Therefore, when you pass a string literal to a function that takes a std::string, a temporary std::string that holds the contents of the literal must be created. This is done with the conversion constructor of std::string.
A const& is allowed to be initialized from a temporary, which allows conversion constructors to work their magic. A const* 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 a std::string value if you have C++11 move constructors available.