I'm having trouble with this function below:
char* GetPlayerNameEx(int playerid)
{
char Name[MAX_PLAYER_NAME], i = 0;
GetPlayerName(playerid, Name, sizeof(Name));
std::string pName (Name);
while(i == 0 || i != pName.npos)
{
if(i != 0) i++;
int Underscore = pName.find("_", i);
Name[Underscore] = ' ';
}
return Name;
}
declaration:
char* GetPlayerNameEx(int playerid);
usage:
sprintf(string, "%s", CPlayer::GetPlayerNameEx(playerid));
Now my problem here is
Removed personal information.
If this has anything to do whith it which I doubt it does, this function is contained within a "Class" header (Declartion).
Also I have no idea why but I can't get the "Code" box to fit over correctly.
Illegal call of non-static member function means that you are trying to call the function without using an object of the class that contains the function.
The solution should be to make the function a static function.
This is normally what causes the error C2352:
class MyClass {
public:
void MyFunc() {}
static void MyFunc2() {}
};
int main() {
MyClass::MyFunc(); // C2352
MyClass::MyFunc2(); // OK
}
If making it static is not an option for you, then you have to create an instance of the class CPlayer.
Like this:
CPlayer myPlayer;
myPlayer.GetPlayerNameEx(playerid);
You cannot create these functions as static (without a lot of tweaking) because you are attempting to modify the data of a specific instance. To fix your problem:
class CPlayer
{
public:
// public members
// since you are operating on class member data, you cannot declare these as static
// if you wanted to declare them as static, you would need some way of getting an actual instance of CPlayer
char* GetPlayerNameEx(int playerId);
char* GetPlayerName(int playerId, char* name, int size);
private:
// note: using a std::string would be better
char m_Name[MAX_PLAYER_NAME];
};
// note: returning a string would be better here
char* CPlayer::GetPlayerNameEx(int playerId)
{
char* Name = new char[MAX_PLAYER_NAME];
memset(Name, MAX_PLAYER_NAME, 0);
GetPlayerName(playerId, m_Name, sizeof(m_Name));
std::string sName(m_Name);
std::replace(sName.begin(), sName.end(), '_', ' ');
::strncpy(sName.c_str(), Name, MAX_PLAYER_NAME);
return Name;
}
// in your usage
CPlayer player;
// ...
sprintf(string, "%s", player.GetPlayerNameEx(playerid));
CPlayer::GetPlayerNameEx(playerid)
You can't use the scope (::) operator on a class type to call a function unless it is a static function. To call a function on an object, you actually have to create the memory for that object first (via making a CPlayer variable somewhere) and then calling the function on that object.
Static functions are global and specifically do not mess with member variables of the class (unless they are also static) which makes them valid to call without the scope of an actual object instance.
Related
Currently learning some c++ and unsure why this is giving me "expression must have pointer type".
Mapp.hpp
class RouteMap
{
public:
RouteMap();
string getCurrent_();
void StoreCity(string b);
private:
std::vector<string>* cities();
string current_;
};
mapp.cpp
RouteMap::RouteMap(){}
string RouteMap::getCurrent_()
{
return current_;
}
void RouteMap::StoreCity(string b)
{
cities->push_back(b); //Error
}
std::vector<string> RouteMap::cities()
{
return std::vector<string>();
}
I am attempting to have a vector Cities as a private member so that when I run the member function StoreCity(string x), it would push_back the specific string into Cities.
I'm going to take a stab and say that the problem is cities() is a function and requires parenthesis:
cities()->push_back(b);
Edit Just found the implementation of cities() (silly me). You have another problem, and that is that your declaration and implementation don't match.
// declaration
std::vector<string>* cities();
// implementation. Notice the lack of a pointer type return
std::vector<string> RouteMap::cities()
{
return std::vector<string>();
}
It's also weird that you're returning a new vector each time. You probably want a member variable:
class RouteMap
{
//...
private:
std::vector<string> my_cities;
//...
};
and then return the member variable from there:
std::vector<string>* RouteMap::cities()
{
return &my_cities;
}
Edit2: It has come to my attention that you probably, while you could fix these things like this and get it working, the truth is that you probably don't mean for cities() to be a function at all. You probably mean for it to be a member variable instead:
class RouteMap
{
//...
private:
std::vector<string> cities;
//...
};
This requires no implementation, (aka RouteMap::cities(){}), and you can just use it inside any member function (because it's a private member) like current_.
All my searching has yielded little in terms of C++ solutions....
I have a class that gets info out of config files, I have a static function that gets the site number out of a different config file. To avoid duplicating the code I create an instance of the class inside of the static function. This compiles without any warnings (with -Wall).
Unfortunately I can't find any information on whether or not it's undefined behavior. Is it ?
#include <iostream>
#include <fstream>
#include "srxDSLog.H"
extern SrxDsLog *Logger;
class Stanza {
private:
std::string config_file_path_;
public:
Stanza(std::string config_file_path) {
config_file_path_ = config_file_path;
}
std::string GetValue(std::string config_section, std::string config_setting) {
std::ifstream config_file(config_file_path_.c_str(), std::ios::in);
std::string current_section, line;
for ( ; std::getline(config_file, line); ) {
line = rtrim(line);
if (line.find(" ") == std::string::npos && line.find(":") != std::string::npos) {
current_section = line.substr(0, line.find(":"));
continue;
}
if (current_section == config_section) {
if (line.find(config_setting) != std::string::npos && line.find("=") != std::string::npos) {
return line.substr(line.find(config_setting) + config_setting.length() + 3); // we're getting the string starting after the name of the setting + " = " + 1. We're assuming there's exactly 1 space
}
}
}
if (current_section.empty()) {
Logger->WriteLog("Couldn't find section: " + config_section, LOG_ERROR, "Stanza::GetValue");
return "";
}
else {
Logger->WriteLog("Couldn't find setting: " + config_setting, LOG_ERROR, "Stanza::GetValue");
return "";
}
Logger->WriteLog("Somehow reached the end of function without returning", LOG_ERROR, "Stanza::GetValue");
return "";
}
static std::string rtrim(std::string input) {
if (input.find_last_not_of(" ") == input.length() - 1) {
return input;
}
else {
return input.substr(0, input.find_last_not_of(" ") + 1);
}
}
static int GetStoreNumber() {
Stanza store_config("/u/data/store.cfg");
std::string store_number = store_config.GetValue("store", "site");
return atoi(store_number.c_str());
}
};
This is perfectly legal and totally safe.
It sometimes helps to think of a static function as a free function that just happens to be scoped inside of the class it's declared in. You could declare objects of type Stanza in a free function, so it's fine to do so in a static member function inside of Stanza.
There are very few circumstances where it's risky to define an object of type T inside of a member function of T, and those cases are primarily constructors or destructors where you have to worry about accidental recursion.
It's perfectly acceptable code. I can't point you at a reference that says it's not undefined behavior because it's not a case anybody has thought to point out as being worrisome.
A static function is just like an ordinary friend function not inside the class. If you would be able to create objects if your type in an ordinary unrelated function, you should be able to inside a static function as well.
As an example, I have static functions who's whole purpose in life is to construct members of my class. I use these to make sure that all instances of my class are constructed using new and are referenced via shared_ptr. How do I call ::std::make_shared on a class with only protected or private constructors?
Unfortunately I can't find any information on whether or not it's undefined behavior. Is it ?
It's perfectly fine in terms of behavior of the function.
What's not clear to me is whether you need a non-static instance of the class in the static member function.
If the contents of the file "/u/data/store.cfg" are not expected to change during execution of the program, you could use a static variable.
static int GetStoreNumber() {
static Stanza store_config("/u/data/store.cfg");
std::string store_number = store_config.GetValue("store", "site");
return atoi(store_number.c_str());
}
You can refine it further to use:
static int GetStoreNumber() {
static int number = getStoreNumber("/u/data/store.cfg");
return number;
}
static int GetStoreNumber(std::strinc const& filename) {
Stanza store_config(filename);
std::string store_number = store_config.GetValue("store", "site");
return atoi(store_number.c_str());
}
If the contents of the file "/u/data/store.cfg" are expected to change during execution of the program, you can keep the function as you have it.
I'm having a little bit of a hard time explaning the problem, so here's a simple rundown of my code:
Imagine I have a class called 'character'
#include "myEnums"
#include "weapon"
character {
protected:
string characterName;
weapon* myWeapon;
public:
string getCharacterName();
void setCharacterName( string );
string getMyWeapon();
void setMyWeapon();
}
Then within 'setMyWeapon' I use this simplified code.
void character::setMyWeapon() {
this->myWeapon = new weapon("longsword");
//this->myWeapon = new weapon(myEnums::LONGSWORD); //Ideally this
}
string getMyWeapon() {
return this->myWeapon.tostring();
}
But when I type the '.' for 'myWeapon' there's no members, anyone know whatup? Assume 'tostring' is defined in 'weapon.h'...
Since myWeapon is a pointer, you need to dereference it to access the pointee's members:
myWeapon->tostring()
// ^^^^
int CPMSifDlg::EncodeAndSend(char *firstName, char *lastName, char *roomNumber, char *userId, char *userFirstName, char *userLastName)
{
...
return 1;
}
extern "C"
{
__declspec(dllexport) int start(char *firstName, char *lastName, char *roomNumber, char *userId, char *userFirstName, char *userLastName)
{
return CPMSifDlg::EncodeAndSend(firstName, lastName, roomNumber, userId, userFirstName, userLastName);
}
}
On line return CPMSifDlg::EncodeAndSend I have an error :
Error : a nonstatic member reference must be relative to a specific object.
What does it mean?
EncodeAndSend is not a static function, which means it can be called on an instance of the class CPMSifDlg. You cannot write this:
CPMSifDlg::EncodeAndSend(/*...*/); //wrong - EncodeAndSend is not static
It should rather be called as:
CPMSifDlg dlg; //create instance, assuming it has default constructor!
dlg.EncodeAndSend(/*...*/); //correct
Only static functions are called with class name.
classname::Staicfunction();
Non static functions have to be called using objects.
classname obj;
obj.Somefunction();
This is exactly what your error means. Since your function is non static you have to use a object reference to invoke it.
CPMSifDlg::EncodeAndSend() method is declared as non-static and thus it must be called using an object of CPMSifDlg. e.g.
CPMSifDlg obj;
return obj.EncodeAndSend(firstName, lastName, roomNumber, userId, userFirstName, userLastName);
If EncodeAndSend doesn't use/relate any specifics of an object (i.e. this) but general for the class CPMSifDlg then declare it as static:
class CPMSifDlg {
...
static int EncodeAndSend(...);
^^^^^^
};
I have a variable, which is a member of one of my classes, that another is in need of, but I'm not sure how to effectively pass the value between them without using a global variable, which is something I'd like to avoid if at all possible. I know I could create an object, but that would invoke the constructor of the originating class which would execute a number of functions and write the needless results to memory, which would be wasteful of system resources.
Is there an easy way to pass this value between the two functions?
Update: The class that is in need of the variable, called no_of_existing_devices. The purpose of class Initialise is to open up a file and count the number of lines of test it contains, and place that number in the variable int no_of_existing_devices, which is then used by the Device::Device() to create an object for each
class Device
{
public:
void view_attribute_list();
void set_attribute();
Device();
};
Device::Device()
{
for (int count = 0; count < no_of_existing_devices; count ++)
{
// Create an object for each iteration, up to a maximum of no_of_existing_devices
}
}
The class of which this variable is a member
class Initialise
{
public:
int no_of_existing_devices;
bool initialisation;
string existing_device_list[100];
void initialise_existing_devices();
Initialise();
};
Initialise::Initialise()
{
no_of_existing_devices = 0;
}
void Initialise::initialise_existing_devices()
{
string line;
ifstream DeviceList;
DeviceList.open("devices/device_list");
while (true)
{
getline(DeviceList, line, '\n');
if (DeviceList.eof())
{
break;
}
++ no_of_existing_devices;
}
DeviceList.close();
DeviceList.open("devices/device_list");
for (int i = 0; i < no_of_existing_devices; i ++)
{
getline(DeviceList, line, '\n');
existing_device_list[i] = line;
}
Device existing_devices[no_of_existing_devices];
!initialisation; // Existing devices are now initialised
}
Okay, from what I understand:
You don't want to have a global
You don't want to have a static
You don't want to introduce a dependency between Device and Initialise
There is one other option, assuming something owns Device and Initialise, move the no_of_existing_devices up to there, then construct both Device and Initialise with a reference to this variable...
In a similar circumstance I was just passing the pointer to the member --- I had to invoke a member function then, so it was a pointer to the member function, http://www.parashift.com/c++-faq-lite/pointers-to-members.html
It's a bit messy, but it works :-).
If the variable in the originating class can hold a value without an instance of the class I would assume that the variable is static. If not create a public static member of the class. And use it in the target class.
Something like:
// .h file
class A
{
public:
static int a;
}
// .cpp file
int A::a = 123;
// .cpp file of class B
void B::foo()
{
cout << A::a;
}
If it is a class attribute (internal variable), then you can obtain a reference through a get method. Otherwise, you can use the friend keyword on the class you want to access the attribtue from the other For example, if you declare friend class B; on class A, the attributes of the class B will be accessible on the class A.
I suggest you use the first method in order to maintain your code OO pure ;)
Edit: of course, if you access through a reference there are no resources wasted :)
Edit 2: use a static method on Initialise class that returns the no_of_existing_devices and call Initialise::NoOfExistingDevices() on the Device class. If you want to resources use a pointer like this:
public static int* Initialise::NoOfExistingDevices() {
return &no_of_existing_devices;
}
By the way, I advise you to turn the variable private.