I would like to convert this constructor's argument from const char* to std::string, but I don't know how to copy the new name to name properly.
Player::Player(const char* name) :
level(1),life(1),strength(1),place(0){
char* new_player_name = new char[strlen(name) + 1];
strcpy(new_player_name, name);
this->player_name = new_player_name;
}
Player::Player(string name) :
level(1),life(1),strength(1),place(0){
string new_player_name(' ',name.length() + 1); //#1
// I didn't know how to proceed
}
The classes data-members:
class Player {
char* player_name;
int level;
int life;
int strength;
int place;
};
Consider making player_name a std::string.
Then your constructor could start
Player::Player(const char* name) : player_name(name)
{
and you don't need to fiddle about with all those dynamically allocated char arrays.
You could change the type of name to a const std::string& too:
Player::Player(const std::string& name) : player_name(name)
{
Related
given class with field const char* filename; so that the name of the class is for example MyClass.
#include <cstring>
class MyClass{
const char* filename;
public:
MyClass(const char* name);
};
How can I initialize the field filename by name?
NOTE: I must do it with strcpy function.
Is there a way to do this with a initialization list?
Is there a way to do this with a initialization list?
There is, you need to use strdup function:
class MyClass {
const char* filename;
public:
MyClass(const char* name)
: filename(strdup(name))
{
if(!filename)
throw std::bad_alloc(); // strdup failed.
}
~MyClass() {
free(const_cast<char*>(filename));
}
MyClass(MyClass const&) = delete;
MyClass& operator=(MyClass const& b) = delete;
};
MyClass::MyClass(char const* filename)
: filename(strcpy(new char[strlen(filename) + 1], filename))
// ^^^ space for trailing 0!
{ }
As using new, in case of allocation failure a std::bad_alloc will be thrown and strcpy never be called, so we are fine.
Do not forget to delete[] filename; in the destructor (not free, you did not malloc!), otherwise you have a memory leak.
Edit (stealing the ideas from Maxim's comments...):
Using a lambda, you could profit from the more efficient memcpy:
MyClass::MyClass(char const* filename)
: filename([](char const* value)
{
size_t len = strlen(filename) + 1;
return reinterpret_cast<char*>(memcpy(new char[len], value, len));
}())
{ }
You get all this trouble for free, though, if you switch to std::string instead:
MyClass
{
std::string filename;
public:
MyClass(char const* filename) : filename(filename) { }
};
You don't even need an explicit destructor any more (provided there is nothing else to clean up...) – use filename.c_str() in a char const* getter, if needed.
Working with char* is very tricky. I recommend you to use string to store filename. But you still want to use char*. You can try as follows:
MyClass(const char* name)
{
filename = new char[100];
for(int i=0;name[i]!='\0';i++)
{
filename[i]=name[i];
}
}
Alright, so this was a task I had on my test.
You need to create a class User with a const int userID so that each User object will have an unique ID.
I was asked to overload the constructor with 2 parameters: key, name. If the key was 0 then the User will have an unique ID, else the user will get userID = -1.
I've done this:
class User{
private:
static int nbUsers;
const int userID;
char* name;
public:
User(int key, char* name) :userID(nbUsers++){
if (name != NULL){
this->name = new char[strlen(name) + 1];
strcpy(this->name);
}
}
};
I don't know how to firstly check if the key parameter is 0 and then initialize the const userID.
Any thoughts?
You can use the ternary operator, so that it can be called directly in the constructor initialization list:
class User
{
private:
static int nbUsers;
const int userID;
char* name;
public:
User(int key, char* name) : userID(key == 0 ? -1 : nbUsers++)
{
// ...
}
};
The standard guarantees that only one of the branches will be evaluated, so nbUsers won't be incremented if key == 0.
Alternatively, you can use a helper function:
int initDependingOnKey(int key, int& nbUsers)
{
if(key == 0) return -1;
return nbUsers++;
}
class User
{
private:
static int nbUsers;
const int userID;
char* name;
public:
User(int key, char* name) : userID(initDependingOnKey(key, nbUsers))
{
// ...
}
};
I am trying to create a Person class in which I have decided to keep the name and gender constant. Here is the class definition:
class Person
{
const char *name;
int age;
const char *gen;
protected:
Person(const char *, const int ,const char *); // I want to use this class as a Base class
public:
~Person();
}
Now my problem is how to initialize the constant data members. I know that I have to use initialization lists for this task but even then how do I allocate memory for the char pointers with new? Also I cannot initialize these pointers in the constructor body. Please help me find a solution.
You can use the initializer list as following, you don't need to allocate the char array in this construction. I have simplified the class, as your question is about the const char*.
#include <iostream>
#include <string>
class Person
{
public:
Person(const char* name, const std::string better_name) :
name(name), better_name(better_name) {}
void print_name()
{
std::cout << name << " and " << better_name << std::endl;
}
private:
const char* name;
const std::string better_name;
};
int main()
{
Person person("Billy", "Better Billy");
person.print_name();
return 0;
}
I'm trying to initialize an instance of a class called "Winery" using an initialization list in the constructor for another class called "List." The problem is that when I hand the Winery constructor a winery to copy, it fails to copy the information.
This the header file for the Winery class:
class Winery
{
public:
Winery(const char * const name,
const char * const location,
const int acres,
const int rating);
virtual ~Winery(void);
const char * const getName() const { return name; }
const char * const getLocation() const { return location; }
const int getAcres() const { return acres; }
const int getRating() const { return rating; }
private:
char *name;
char *location;
int acres;
int rating;
};
Here is the relevant part of the header file for my List class:
struct Node
{
Node(const Winery& winery);
Winery item;
Node *nextByName;
Node *nextByRating;
};
Here is the constructor in my List class:
List::Node::Node(const Winery& winery) :
item(winery.getName(),
winery.getLocation(),
winery.getAcres(),
winery.getRating()),
nextByName(nullptr),
nextByRating(nullptr)
{
}
From what I see, it looks like I'm doing everything I need to be doing. The data members of the winery that I'm passing to the constructor are private, so I'm trying to get them via the functions that get information. They're in the proper order and everything.
The pointers work just fine after I initialize them, but the information isn't there, so I really don't know what to do here. If you're wondering, this is for an assignment and we have to use initialization lists (I've tried it without them and that doesn't work either so I really don't know what to do).
Here is my Winery constructor:
Winery::Winery(const char * const name,
const char * const location,
const int acres,
const int rating) :
acres(acres),
rating(rating)
{
char *newName = new char[sizeof(name) + 1];
char *newLocation = new char[sizeof(location) + 1];
}
From the looks of it, these lines:
char *newName = new char[sizeof(name) + 1];
char *newLocation = new char[sizeof(location) + 1];
do essentially nothing, as the location and name strings are not assigned or even written, which is probably the root of the problem. Your acres and rating should have been properly constructed, however.
Here is a working version I've created (also at Ideone):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
class Winery
{
public:
Winery(const char * const name, const char * const location, const int acres, const int rating) :
name(strdup(name)),
location(strdup(location)),
acres(acres),
rating(rating)
{
}
virtual ~Winery(void)
{
free(name);
free(location);
}
const char * const getName() const { return name; }
const char * const getLocation() const { return location; }
const int getAcres() const { return acres; }
const int getRating() const { return rating; }
private:
char *name;
char *location;
int acres;
int rating;
};
struct Node
{
Node(const Winery& winery);
Winery item;
};
Node::Node(const Winery& winery) :
item(winery.getName(), winery.getLocation(), winery.getAcres(), winery.getRating())
{
}
int main()
{
Winery winery("Mission Hill Winery", "Kelowna, BC, Canada", 646, 4);
Node node(winery);
printf("%s\n", node.item.getName());
printf("%s\n", node.item.getLocation());
printf("%i\n", node.item.getAcres());
printf("%i\n", node.item.getRating());
}
Output:
Mission Hill Winery
Kelowna, BC, Canada
646
4
can you help me with composition in C++ please?
I have class User, who contains:
User.h
class User
{
public:
std::string getName();
void changeName(std::string nName);
std::string getGroup();
void changeGroup(std::string nGroup);
User(std::string nName, std::string nGroup);
~User(void);
private:
std::string name;
std::string group;
};
Now I define in class Honeypot:
Honeypot.h:
class Honeypot
{
public:
User us;
I have constructor:
Honeypot (std::string name, std::string ip, int numberOfInterfaces, std::string os);
in Honeypot.cpp:
Honeypot::Honeypot(std::string name, std::string ip, int numberOfInterfaces, std::string os):us(nName, nGroup){
this->name = name;
this->ip = ip;
this-> numberOfInterfaces = numberOfInterfaces;
this->os = os;
}
But this syntax is not correct. Errors are:
IntelliSense: expected a ')', 'nGroup' : undeclared identifier and more on line :us(nName, nGroup){...
Thank you for help.
nName and nGroup need to be parameters of the Honeypot constructor; as the compiler indicates, they're undeclared.
Honeypot::Honeypot(std::string name, std::string ip,
int numberOfInterfaces, std::string os,
std::string userName, std::string userGroup)
: us(userName, userGroup)
{
this->name = name;
this->ip = ip;
this->numberOfInterfaces = numberOfInterfaces;
this->os = os;
}