C++ passing const string references in methods? - c++

I'm trying to initialize a private variable of my Class passing a const string &aString to it as parameter.
Here's my method:
void Image::initWithTextureFile(const std::string &inTextureName)
{
Texture2D *imTexture = TEXTURE_MANAGER->createTexture(inTextureName);
if(imTexture)
{
texture = imTexture;
scale = 1.0f;
name = inTextureName; //name is a private string variable inside my class
initImplementation();
}else {
printf("Could not load texture when creating Image from file %s\n",inTextureName.c_str());
}
}
My problem is the following, when I call this method I do it like:
myInitializer.initWithTextureFile("myFile.bmp");
When I'm inside the scope of initWithTextureFile the name variable takes the value of inTextureName. For this example if I cout << name << endl; inside initWithTextureFile i would get "myFile.bmp"
But when I leave the scope of the function, name looses it's value, so when i cout << name << endl; I get nothing printed in the console.
Could anyone point me out to what's going on here?
Name is declared:
private:
std::string name;

If you're outside the class scope, and cout << name compiles at all, it means you have another variable named name, and that's what's being picked up. If you want to refer to it outside the class, you'll have to come up with a way that will export it. You might, for example, have a member function like const std::string &GetName() { return name; }.

You either omitting something in your description or are not showing appropriate code that could help solve your problem.
This works:
#include <iostream>
#include <string>
using namespace std;
struct A
{
void f(const string& str) { name = str; }
void g() { cout << name << endl; }
string name;
};
int main()
{
A a;
a.f("test");
a.g();
}
Output:
test

That should work. Are you sure it is not being modified somewhere else, such as in initImplementation?

The problem probably have to do with the name variable : is it a pointer or ref to string instead of a plain string ?

The only reasonable explanation here is that you must be working with two different name objects. The one you declared as a class member should hold its value when you exit the method. It is just that outside the class method you must be printing a completely different name, which is empty.

I was going to say something about short-lived stack objects but I realised that was wrong. What it could be is something to do with exporting the containing class from a DLL.
If so, you might find a warning like this:
c:\yourclass.h(7): warning C4251: 'YourClass::name_' : class 'std::basic_string<_Elem,_Traits,_Ax>' needs to have dll-interface to be used by clients of class 'YourClass'
This thread describes more.

How is 'name' declared? It seems like maybe it's declared as a reference instead of an object.

Try:
name = std::string(inTextureName);

Related

Set and get member functions manipulation of data members

So I'm an newbie to programming and I have encountered a
case for which I suppose qualifies as an authentic question
in this awesome forum. Is there a way to write statements inside my get functions so that I can obtain all the changed data member values without having to create multiple get functions
for each data member?
Regards
I am practicing building programs which are easy to maintain by localizing the effects to a class's data members by accessing and manipulating the data members through their get and set functions. In this regard I have two data members for which I wish to change. After compiling, the set functions works well by changing the values but the get functions can only return one of the data member values at a time.
class GradeBook
{
public:
void setCourseName(string code,string name)
{
CourseCode = code;
CourseName = name;
}
string getCourseName()
{
return CourseCode;
return CourseName;
}
void displayMessage()
{
cout<<"Welcome to the GradeBook for: \n" <<getCourseName()
<<endl;
}
private:
string CourseName;
string CourseCode;
};//end class GradeBook
After compiling and running the program, the program outputs the CourseCode but the CourseName doesn't get displayed. I had to create two get functions each to obtain the two data members. I don't want to have 2 get functions to obtain the data member values. I just want to use one get function to keep the code at minimum.I wish to use one get function to return two values for each data member. I have already tried using one return statement and separated the data members with a comma.
Your idea of using return twice cannot work, the first return will return control to the caller and the second will never be executed. You should have got warning about it from your compiler.
I believe that an initial solution could be to use std::pair (docs: https://en.cppreference.com/w/cpp/utility/pair), see snippet below.
NOTE: using namespace std; (which is most likely what you are doing in the code you do not show), is a bad practice, consider using the fully qualified name
#include <string>
#include <utility>
#include <iostream>
//Bad practice, I added it only to keep differences with OP code small
using namespace std;
class GradeBook
{
public:
void setCourseName(string code,string name)
{
CourseCode = code;
CourseName = name;
}
std::pair<string, string> getCourseName()
{
return {CourseCode, CourseName};
}
void displayMessage()
{
//only in C++17
auto [code, name] = getCourseName();
cout<<"Welcome to the GradeBook for: \n" << code << " - " << name
<<endl;
}
private:
string CourseName;
string CourseCode;
};//end class GradeBook
Note that auto [code, name] is a feature called structured binding, available only in C++17, if you have an older compiler, you have to return a std::pair<std::string, std::string> and access its elements using the member variables first and second.
Now, std::pair is good for this contrived example, but, for your case, you might want to consider doing something a bit more readable, because the elements of the pair have the same type so the user of your library will have difficulties remembering what is the first and second element. So you might want to use a custom-made struct with some more meaningful names.
#include <string>
#include <utility>
#include <iostream>
//Bad practice, I added it only to keep differences with OP code small
using namespace std;
struct CourseCodeAndName{
std::string code;
std::string name;
};
class GradeBook
{
public:
void setCourseName(string code,string name)
{
CourseCode = code;
CourseName = name;
}
CourseCodeAndName getCourseName()
{
return {CourseCode, CourseName};
}
void displayMessage()
{
auto codeAndName = getCourseName();
cout<<"Welcome to the GradeBook for: \n" << codeAndName.code << " - " << codeAndName.name
<<endl;
}
private:
string CourseName;
string CourseCode;
};//end class GradeBook
See this example. Alternatively you can use std::tuple.
class GradeBook
{
/* ... */
public:
std::pair<std::string, std::string> get(){
return std::make_pair(CourseName, CourseCode);
}
};
int main()
{
GradeBook book1("Hello","World")
auto result = book1.get();
cout << result.first << result.second;
}
If you write:
return x,y;
or:
return x;
return y;
You should know that in first case you get the last value (you get y), and in second case you get the value of first return (you get x, because as soon as compiler see return, function will return the value, and then function will go in epilogue state (cleaning of stack memory assigned to function, both inline and non-inline function).
And about the use of get function it's normal. If you want to use the value to do something of logic (not to display), yes you should use a lot of get function. Instead if you want to display the values, use a void function, for example "void printData();", and inside it write code to print data. You probably setted the class variables as private (following the encapsulation rules) so you will have access to them inside the print function.

Not able to use function variables ? Error expression must have class type

Hey i want to use the function wolves variable in the storyline and im trying to do this :
"\nYou awake on a beach to the sound of"<< Wolves().name; " starving and blood hungry,"
"\nThere is a Rock on the ground. You pick it up";
inventory.push_back("Rock");
But Wolves().name; there is an error as mentioned in the title. Why cant i do this?
Here is the code for the function Wolves:
void Wolves()
{
string name = "Wolves";
int health = 20;
hitPoints() +1;
}
You can't access variables defined in a function from outside the function in C++, but you can change it to a class:
class Wolves {
public:
string name;
// ...
Wolves(); // Constructor
//...
}
To access it you can use
Wolves wolve;
wolve.name = "whateverName"; // or set it in the constructor
cout << wolve.name << endl;
What you did in there is create local variables within the function. Once the function exits, they no longer exist. What you want to do is make a Wolves class and create public member variables to do what you want. For an example,
class Wolves {
public:
string name;
int health;
Wolves(string name, int a);
}
Then on the main function,
Wolves w("Bob", 20);
cout << "The name is: " << w.name << endl;
Will output "The name is: Bob"
void functions don't really do anything unless you pass the value in by reference. If you want to alter the object via void function, you should do something like
void Wolves(Wolves & wolfToChange)
{
wolfToChange.name = "Bob";
}
and that will directly alter the object.
You declared "name" as a local variable in a function called Wolves(), but the code that you were referring to expects the function Wolves() to return an object that has an accessible member name. That is why the compiler is complaining.
The way you wrote the code suggests that Wolves should be a class or struct, not a function.

C++ geting error while using function inside class

I can't figure out why I get this error: "the function was not declared". I am still a newbie at programming, but I am trying my best to learn it!
so here is my code, I would be realy greatful if you could help me:
main:
#include <iostream>
#include <vector>
#include "szovegkezelo.h"
using namespace std;
int main()
{
string sz;
beolvas(sz);
kiir(sz);
return 0;
}
header:
#ifndef SZOVEGKEZELO_H_INCLUDED
#define SZOVEGKEZELO_H_INCLUDED
#include <iostream>
using namespace std;
class szovegkezelo {
protected:
string sz;
public:szovegkezelo
void beolvas(string &sz);
void kiir(string t);
};
#endif // SZOVEGKEZELO_H_INCLUDED
cpp:
#include "szovegkezelo.h"
#include <iostream>
void szovegkezelo::beolvas(string &sz)
{
getline(cin, sz);
}
void szovegkezelo::kiir(string t)
{
cout << "a beadott szoveg: " << t << endl;
cout << "a string hossza: " << t.size() << endl;
}
From what it looks like, you are trying to call a classes function (method) called 'beolvas' from 'main' but because it belongs to a class, you can't call it like that, you need to create an instance of that class and call the method on that instance, or make the function static and call it from the class.
Your first option is to create an instance of the class and then call the methods on the class like so:
int main()
{
string sz;
szovegkezelo szov;
szov.beolvas(sz);
svoz.kiir(sz);
return 0;
}
Your second option is to make the functions in your class static, this way they will not need an instance of the class to be called:
int main()
{
string sz;
szov::beolvas(sz);
svoz::kiir(sz);
return 0;
}
static void szovegkezelo::beolvas(string &sz)
{
getline(cin, sz);
}
static void szovegkezelo::kiir(string t)
{
cout << "a beadott szoveg: " << t << endl;
cout << "a string hossza: " << t.size() << endl;
}
Been a while since I've done anything static in c++ so please correct me if I've done something wrong in the second option.
Your two or more data types... error comes from a misuse of...something...after that public access specifier.
Change this:
public:szovegkezelo
to this:
public:
If you're trying to make a constructor, it needs to be declared like any other function, minus the return type.
Your other error occurs because this function was declared improperly.
Other than that, you need to create an object before you can call the class's functions. Each object has it's own set of variables that the functions work on. I would seriously recommend reading a good beginner C++ OOP book.
Somewhere in main, you need to create an object:
szovegkezelo myObject;
Then, use it to call functions:
myObject.kiir (sz);
Finally, note that your data members should typically be declared with the private access specifier. protected has nothing to do with normal classes that are not inherited from.
couple of things :
1) In main you have not instantiated an object of szovegkezelo and you are trying to call beolvas . Compiler is looking for a free function beolvas whereas you have declared beolvas as member function
2) public:szovegkezelo is not right if you are looking for a default constrcutor that does nothing don't have that line else if you need to do something specific with default construct declare it as szovegkezelo() in header.
3) as mentioned in comments it is not a good practice to put
using namespace std in header files or any using namespace

C++ Pointers help?

I need a little bit of help with using pointers in C++. Sorry to seem beginner but I really can't quite understand them. I have read the tutorial on pointers on the cplusplus.com website, so please don't suggest that.
I basically have a variable which holds the name of another variable, and I wish to access that variable through the holder one. I believe I need to use pointers, correct me if I'm wrong though.
E.g.
int a;
string b;
a = 10;
b = "a";
I need to access the variable "a" through the contents of variable "b".
Just to put this into better perspective, this is how I am using it:
int a;
a = 20;
void getVar(string name) {
cout << name;
}
getVar("a");
But as you can see, on the fifth line, that will just cout the value of name, in this case "a", but I want it to cout the value of the variable which name contains, so I want it to output "20".
Any help here would be much appreciated.
If you need to associate a name with a value, consider associative arrays otherwise known as dictionaries and maps. The Standard Template Library has std::map that you can use to associate text with a value:
#include <map>
#include <string>
std::map<std::string, int> my_map;
my_map["A"] = 20;
cout << my_map["A"] << endl;
What you are thinking of is called (Reflection) which C++ does not support. You can however use pointers to access what is in a variable it points to:
int a = 5; //int variable that stores 5
int *b = &a; //int pointer that stores address of a
(*b) = 10; //stores 10 into address that b points to (a)
cout << a; //prints 10
What you are trying to achieve is not possible in a compiled language (not considering reflection). You might accomplish something similar using a map data structure.
theMap["a"] = 20;
and a corresponding
void getVar(string key){
cout << theMap[key];
}
that can be called with
getVar("a");
Note that in this extremely simple sample theMap has to be in scope for the function, like in a class or a namespace.
If you use pointers you are just using a level of indirection not at all suited for your example. See Chads answer for instance.
Theres no real way for you to access variables by name like that unless you create some kind of container class that has a name member that you look up by. I'm not sure what this has to do with pointers though.
What you're asking for is called "reflection" or "introspection" - the ability to use design-time names for your program's objects (classes, variables, functions, etc) in run time. C++ does not support that out of the box - the design-time names are stripped upon compilation.
There are some libraries that provide that capability in C++; but there are also languages where reflection is is part of the language. Python or JavaScript, for example.
Maybe this could suit you:
int a = 5;
class b {
public:
b(int &x) { ref_ = x; }
int operator()(void) { return ref_; }
private:
int &ref_;
}
b my_b(a);
my_b() /* -> 5 */;
Your code does not use pointers. you're trying to convert a string into an identifier and print it's result, I don't know whether that's possible or not. If you intended using pointer your code should've looked like this:
int a = 20;
int* b = &a;
cout << *b;
quick fix for outputting integers only:
int a;
a = 20;
void getVar(int name) {
cout << name;
}
getVar(a);
If you need the function to work for any type of variable, maybe think about some template function.
Edit: Here is the code for the template program:
#include <iostream>
#include <string>
using namespace std;
template <class T>
void getVar(T name){
cout<<name<<endl;
}
int main()
{
string x="hee";
int y=10;
getVar(x);//outputs hee
getVar(y);//outputs 10
return 0;
}

Cpp some basic problems

My task was as follows :
Create class Person with char*name and int age. Implement contructor using dynamic allocation of memory for variables, destructor, function init and friend function show. Then transform this class to header and cpp file and implement in other program. Ok so here's my Person class :
#include <iostream>
using namespace std;
class Person {
char* name;
int age;
public:
Person(){
int size=0;
cout << "Give length of char*" << endl;
cin >> size;
name = new char[size];
age = 0;
}
Person::~Person(){
cout << "Destroying resources" << endl;
delete [] name;
delete take_age();
}
friend void show(Person &p);
int* take_age(){
return &age;
}
char* take_name(){
return name;
}
void init(char* n, int a) {
name = n;
age = a;
}
};
void show(Person *p){
cout << "Name: " << p->take_name() << "," << "age: " << p->take_age() << endl;
}
int main(void) {
Person *p = new Person;
p->init("Mary", 25);
show(p);
system("PAUSE");
return 0;
}
And now with header/implementation part :
- do I need to introduce constructor in header/implementation files ? If yes - how?
- my show() function is a friendly function. Should I take it into account somehow ?
I already failed to return this task on my exam, but still I'd like to know how to implement it.
Solve many of your issues, by switching from char * to std::string. You'll be glad you did.
The std::string class takes care of memory allocation, and deallocation as well as copying.
If this is homework, convince your professor to use std::string for beginners and save char * for the section on pointers. Also remind your professor that the C++ langauge is different than the C language. This is one of those areas.
You don't need a * when using delete or delete[]. Just supply a pointer variable to it eg.
delete[] name;
Also, your take_age member claims to return a int* but you actually return the int member itself. You need to take the address of the member using & if you want to do that. As #Jerry has commented this is not what you want to do here.
Although some on this site apparently think it is completely acceptable, good practice (see Can a constructor return a NULL value?), you should really refrain from doing things like stream operations within the constructor of your object. Do that stream reading outside and then call the function with the results.
That is, IMHO, the first step you should take.
In a typical case, managing a pointer and block of dynamically allocated memory (such as the name in this case) is enough responsibility for one class. As such, Thomas Matthews is right: you should really use string in this case. If you're going to handle it yourself, you should still split that responsibility off into a class of its own, and embed an object of that class into your Person object. If anything, std::string already tries to do too much; you'd be better off with something that does less, not more.
Your deletes should exact match with your allocations. In this case, the only allocation is:
name = new char[size];
so the only deletion should be:
delete [] name;
As far as friend functions go, you normally want the friend declaration inside the class definition, but the function definition outside the class definition:
class Person {
// ...
friend void show(Person const &);
// ...
};
void show(Person const &p) {
// ...
}
There are other possibilities, but that's the general idea. In particular, a friend is never a member function. What you had was a declaration of one (global) function named show and a definition of a completely separate member function -- that happened to have the same name, but wasn't really the same function at all.
That shows one other point: const-correctness. You were passing the parameter as a reference to Person. Unless it's going to modify the Person object (in which case, show() seems like a poor choice of name), it should probably take a reference to a const object. The same general idea applies to take_age() -- since it only retrieves a value, it should be a const function:
int take_age() const { return age; }
I've probably already tried to cover too much, so I'll shut up for the moment...
I think you should investigate the following pieces of your code (like, what's beneath them, what happens here, etc...)
int * take_age(); // You should return plain `int` here, I assume
~Person(){
cout << "Destroying resources" << endl;
delete *[] name; // Do you understand why did you put `*` here?
delete * take_age(); // Do you understand why did you write this? What behaviour you were trying to achieve?
And, actually, so on. Only when you're done with the basic stuff, I think, you can move on to header designing questions and friend functions.
First off, kudos on trying to find the right way to implement your class, particularly after having missed the answer already.
From your description at the top, I think you may have misunderstood some of what was being asked for this assignment. First, my interpretation would be that setting the value of the name and age should take place in the init() function rather than in the constructor. As mentioned by several other posters, your constructor should simply initialize your class to a known-good state. For example,
Person() {
name = NULL;
age = 0;
}
Then in your initialization function, you can assign the values. Looking at your original init() function, it should probably be mentioned that simply assigning a pointer value (char *) to another pointer (char *) only copies the value of the pointer, not the data that it represents. Thus, for the assignment of the name value you need to calculate the size of the buffer you need, allocate the buffer, and copy the data yourself. A basic init() function would probably look like
init(const char *n, int a) {
// Calculate the required name length plus a NULL-terminator
size_t nameLen = strlen(n) + 1;
// Free any previous value.
if (name != NULL) {
delete[] name;
}
// Allocate the name buffer and copy the name into it.
name = new char[nameLen];
memcpy(name, n, nameLen);
// Store the age.
age = a;
}
Finally, in your destructor you free any resources allocated by your class, in this case the name buffer.
~Person() {
if (name != NULL) {
delete[] name;
}
}
If you have a book or something associated with your class, you may want to review the information on pointers. They can be a bit tricky but are important to learn. I suspect that is why the problem specified using char * for strings rather than the STL string class.
To your question about placing information in header and source files, it is often considered good practice to create a header file that contains the class declaration and member function prototypes and then provide the implementation of your methods in a separate source file. For some simple functions, you can provide an implementation directly in your header file.
The key when providing class member definitions in a separate source file is to provide the class name to properly scope the function (i.e., Person::). So your header file may contain a class definition like
// Header file (e.g., person.h)
class Person {
private:
char *name;
int age;
public:
Person() { name = NULL; age = 0 };
~Person() { if (name != NULL) delete[] name; }
void init(const char *n, int a);
// Other method declarations and/or definitions
};
And then in your source file
// Source file (e.g., person.cpp)
void Person::init(const char *n, int a) {
// ...
}
// Rest of method definitions
Source files that use your person class need only include the header file with your class definition.
I think your problem is with this line:
friend void(Person &p);
What is it needed for.
do I need to introduce constructor in header/implementation files ?
The constructor can be in the .h or the .cpp file. It doesn't matter. Generally if the function is short it is ok to include it in the .h file. Anything longer should go in the .cpp.
my show() function is a friendly function.
Not sure what you mean by this. friend functions exist outside the class definition. Your show function is defined inside the class so does not need to be a friend.
in addition to the previously posted answers, i've got two points of advice for you:
don't use 'friend'. some here may disagree with me, but 'friend' should really not be part of C++ anymore as it goes against what OOP stands for.
naming your methods: avoid naming your methods like 'take_name' or 'take_age'. conventionally, since those are getters, consider naming them 'getName' and 'getAge'. you end up with much more respect from developers this way.