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()
// ^^^^
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_.
Here is my concrete example of what I'm trying to do. I need to have a type of object created by the end of this function so I can store it in something else(not created yet), that is either a string, Id, or expression parameter. The problem I am facing is that I don't know what type of object to create if I haven't done logic yet, and If I create the object inside the if statement while I am doing logic, it will exist no more there. I want to store the objects into a vector of type parameter in another class not listed here. at the end of the code
bool parameter(Predicate& pred)//look for the following: STRING | ID | expression
{
//store a parameter in this predicate
Parameter // <- I don't know which type of object to create yet!!!!
//create parameter
get_grammar_type(token, sfile);
token_type = token.Get_type();
if(token_type == STRING)
{
//would create object of type string here
//can't create object here. It won't exist after.
}
else if(token_type == ID)
{
//would create object of ID string here
//can't create object here. It won't exist after.
}
if(expression(pred))
{
//would create object of Expression here.can't create object here. It won't exist after.
}
//store object in object pred here. Pred has a private member of a vector of type parameters within it.
return true;
}
#ifndef PARAMETER_H
#define PARAMETER_H
#include <string>
#include <vector>
#include "Predicate.h"
using namespace std;
class Parameter
{
public:
private:
}
class String : public Parameter
{
public:
insert_string(string in_string);
private:
string my_string;
}
class ID : public Parameter
{
public:
insert_id(string in_ID);
private:
string my_ID;
};
class Expression : public Parameter
{
private:
Parameter left_parameter;
Parameter right_parameter;
string op;
public:
};
#endif
//also I want to know how I will be able to create left and right parameters in the expression class if i don't know what type they are yet
You can use pointers in this case. Create a Parameter* variable further up, and dynamically allocate the data structure inside one of your if-statements and assign to that pointer. For example:
Parameter *parameter = NULL;
if(token_type == STRING)
{
parameter = (Parameter*) new String();
}
Do something fancier with smart pointers if you don't want to worry about deallocation.
Sorry for the confusing title, basically I have created two classes, one is an object, and the other being a box that contains an array of such objects. so what I want to do is create a function/constructor inside the object class that takes in an array of ints and stores them inside the box. I want to be able to call this function through the box class constructor to initialize these objects. So ive tried something like below but it isnt working at all, since only the first value of the array gets passed through. What am I doing wrong?
#include <iostream>
#include <string>
class object{
string objectName;
int values[];
public:
void createObject(int[]);
}
class Box{
object objects[100];
public:
Box();
}
Box::Box (void){
int array1[2];
int array2[15];
object[1].createObject(array1);
object[2].createObject(array2);
}
Object::Object(int Values[]){
values = Values;
}
You should really use std::vector. The problem with arrays is that they decay to pointers when passed as arguments to functions. As a consequence, If you want to store a private copy of the elements you are forced to use heap-allocated objects and consequently do memory management by hand (with all the pain it causes).
It is much better to rely on data members that permit applying the rule of zero.
Here's a tentative solution:
#include <iostream>
#include <string>
#include <vector>
class object {
public:
object(std::vector<int> const& v, std::string const& object_name): v_(v.begin(), v.end()), object_name_(object_name) {}
private:
std::vector<int> v_;
std::string object_name_;
};
class box {
public:
box(std::vector<object> const& objects): objects_(objects) {};
private:
std::vector<object> objects_;
};
I recommend you instead use a std::vector. Arrays don't really work well being passed to functions. When you define Object::Object(int Values[]) you are simply passing the first element of this array by value. If you were to use vectors, the function would look like this:
Object::Object(std::vector<int> &Values):
values(Values)
{
}
The problem with the code is in your thinking on what the array is. In C++, all an array is, is a memory pointer. The language allows you to pass an index into the array pointer to access whatever chunk of data lives at that index.
Whenever you pass arrays between functions or classes, pass the array name only. It will be interpreted as a pointer, and won't copy any data. When you do this, you must also pass the length of the array.
Granted, most people stick with vector<> because it's easier, takes care of memory leaks (mostly) and is VERY efficient. But I like doing it myself. It's good for you. I would try:
#include <iostream>
#include <string>
class Object
{
string _objectName;
int *_values;
int _myLength;
Object();
~Object();
void createObject(int *pValues, int arrLength);
}
class Box
{
_Object objects[100];
Box();
}
Box::Box(void) {
int array1[2];
int array2[15];
object[1].createObject(array1, 2);
object[2].createObject(array2, 15);
}
Object::Object() {
_values = null_ptr;
_myLength = 0;
}
Object::~Object() {
delete[] _values;
}
void Object::createObject(int *pvalues, int arrLength) {
_myLength = arrLength;
_values = new int[_myLength];
for(int ndx=0; ndx<arrLength; ndx++) {
_values[ndx] = pvalues[ndx];
}
}
-CAUTION-
I just adapted your code you provided, and added some conventions. There are a couple places in the code where I'm not sure what the purpose is, but there you go. This should give you a good head start.
My constructor:
bnf::bnf(string encoded)
{
this->encoded = encoded;
}
copies the string data to a member. (Or does it..?)
I will have a recursive decode method, but would like to avoid writing this->encoded all the time.
How can I validly and simply create an alias/reference to the member within a method?
Will this have overhead best avoided?
You can just pass in a different named parameter. This is assuming that encoded is a private string member of your bnf class
bnf::bnf(string en)
{
encoded = en;
}
In your other functions, you still don't need to write this if you don't want to:
void bnf::printCode(){
cout << encoded << endl;
}
Assuming your class looks like this:
class bnf{
public:
bnf(string en};
void printCode();
//<some other functions>
private:
string encoded;
}
There is nothing wrong with what you're doing now. It's expressive, clear and correct. Don't try to ruin it.
If you're worried about "overhead" with using the this pointer, don't: it's already as efficient as it could possibly be. There is literally no way to make it faster.
If your question is slightly wrong and all you want to do is mention a member variable inside a member function, then:
struct MyClass
{
int x;
void myFunction();
};
void MyClass::myFunction()
{
this->x = 4;
}
The function is equivalent to:
void MyClass::myFunction()
{
x = 4;
}
I'm new to and learning C++. I know a fair amount of Java and some C.
What I want to do is to create an immutable name class that takes in a string value, copies that string to a class field and then eventually hashes it to an ID that can be parsed much more efficiently than a string.
I'm hitting a wall due to a general lack of knowledge of C++ strings. Here's what I have so far...
#pragma once
#include <string>
class Name
{
public:
Name(std::string s);
~Name(void);
int getId();
std::string getName();
private:
int id;
std::string name;
};
and...
#include "Name.h"
Name::Name(std::string s)
{
}
So what I want to do is store the value of s, passed in by the constructor in the "name" private field. As far as I know a new string object must be created and then the value of s must be copied into it.
I also think that the argument s can and should be a string pointer instead of a string object (to prevent an unnecessary copy from occurring). If I'm right then the constructor should look like the following, right?
Name::Name(std::string &s) { ... }
In this case, nothing would need to be done special when passing in a name? IE.
Name n = new Name("Cody");
is perfectly valid? Actually I'm not sure since "Cody" to my knowledge is a constant string or something like that.
So if I'm all on the right track, then what is the proper way to actually copy the value? I'm thinking this is appropriate but I'm not sure.
#include "Name.h"
Name::Name(std::string s)
{
name = new string(s);
}
Thanks for the help in advance, I know it's a basic question but I'm slowly making baby steps into the C++ world. :) - Cody
You are close, your code can be like this after a little massage:
class Name
{
public:
Name(const std::string& s); // add const and reference
~Name(void);
int getId() cosnt; // add const
std::string getName() const; // add const
private:
int id;
std::string name;
};
Name.cpp
Name::Name(const std::string& s):name(s)
{
}
Here :name(s) is called member initializer list.
Name n = new Name("Cody"); is perfectly valid? Actually I'm not sure
since "Cody" to my knowledge is a constant string or something like
that.
No, n is not pointer, it's not like java you need to new for every object. In C++, you do
Name n("Cody");
This will call Name(const std::string& s) to initialize object n and initialize name string with "Cody".
Note: variable n has automatic storage duration, it will be destroyed if it goes out of scope.
To let n on dynamic storage duration, you need to use new/delete pair:
Name *pn = new Name("Cody");
delete pn;
or use smart pointers, you no need to call delete n_ptr; as n_ptr will be destroyed when it goes out of scope as well:
#include <memory>
std::shared_ptr<Name> n_ptr(new Name("Cody"));
EDIT:
To use Name class in other classes, it's the same way when you use string in Name class, you don't have to use pointers.
class TestName
{
public:
TestName(const Name& n):name_(n){ }
private:
Name name_;
};
TestName tn("Cody");
You should use a constant reference to std::string here.
As you said, it would prevent unnecessary copies.. But then why not just a pointer or a constant pointer?
A constant reference would allow you to pass to your function some arguments that would implicitly call the right std::string constructor.
So, in a nutshell, you could do that:
Name::Name(const std::string& s)
{
this->name = s;
}
// Or even better..
Name::Name(const std::string& s):
name(s)
{
}
int main(void)
{
Name nick("hello");
return 0;
}
You can find out about every std::string's constructors on its cplusplus.com's sheet.