Okay, I'm getting rusty or I just never noticed this before. I apologize in advance if this has been asked before, but I could not find anything related to what I'm asking, or I was searching the wrong key word. So Let me get to the point. when passing from a const referenced value from a function IE, the return type is a const reference of a member variable of type vector, I can't seem to use the value. Maybe I'm just super rusty, been programming in PHP and Javascript so I've been away from strong typing for a minute.
However, Let me show you some code to establish what I'm talking about.
#pragma once
#include <vector>
#include <string>
class VectorTest
{
public:
VectorTest()
{
std::string test = "";
for (char letter = 'a'; letter < 'Z'; letter++)
{
test.push_back(letter);
valueToReturn_.push_back(test);
}
}
const std::vector<std::string>& ReturnByConstReference()
{
return valueToReturn_;
}
~VectorTest() {}
private:
std::vector<std::string> valueToReturn_;
};
The above is the Vector test class for simplicity. now for the calling section
#include <vector>
#include <iostream>
#include <string>
#include "VectorTest.h"
void functionTest(const VectorTest* testItem)
{
std::vector<std::string> test((*testItem).ReturnByConstReference);
}
void functionTest(const VectorTest& testItem)
{
std::vector<std::string> test(testItem.ReturnByConstReference());
}
int main()
{
VectorTest testVectorObject;
//this works however the passing to the functions does not.
std::vector<std::string> test(testVectorObject.ReturnByConstReference());
functionTest(&testVectorObject);
functionTest2(testVectorObject);
}
Okay, so I can not figure out why the copy constructor for vector works in main, but if I pass the object VectorTest to the function as a const reference the compiler immediately throws a fit. I know I'm forgetting some rule about passing an object as a reference and then trying to access a function that passes back a private member variable as a const reference so I can avoid the cost of a copy.
This is of course a small scale version of what I'm trying to do, so I understand in this example a copy would not be that expensive.
I'm sure I'm forgetting something as to why this isn't working and how to get it to work, so if someone can refresh my memory I would greatly appreciate it.
Sorry again if this is something that has been asked before, but I'm not sure what term to enter for a search so I could not find my answer. Also sorry for any indention problems, copying from Visual studio to here is a bit annoying.
Also to reiterate, the copy constructor works in main, it's when I pass the object to the included functions, that everything goes side ways. Thank you again for your help, and if anything doesn't make sense let me know.
Your parameters say const VectorTest but ReturnByConstReference is not const.
It would fail in main as well if you declared const VectorTest testVectorObject;
Make the function const:
const std::vector<std::string>& ReturnByConstReference() const
Related
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> big_vector = {5,12,4,6,7,8,9,9,31,1,1,5,76,78,8};
vector<int> a = sub(big_vector);
cout<<a.size();
return 0;
}
vector<int> sub(vector<int> big_vector){
return {big_vector.begin() + 7, big_vector.end() - 2};
}
I get this error and do not know why
main.cpp:18:21: error: ‘sub’ was not declared in this scope
debugging and running different test
In C++ all objects must be declared before they are used.
vector<int> a = sub(big_vector);
Your reliable compiler reads this, and it has absolutely no clue, whatsoever, what this mysterious sub function is all about.
Human eyeballs that are owned by a carbon-based life form can easily see this function, later in the file. But your compiler is a beast of logic. It hasn't read that far ahead, into the source file. That's why, in C++, in this situation the function must be declared:
vector<int> sub(vector<int>);
Put this before the main function. The compiler reads this first, and learns all about this amazing function called sub(), which has one vector<int> parameter, and returns a vector<int> itself. So when it reads the contents of main(), which calls this function, it knows exactly what it's all about, and can proceed further.
Or, you can simply put the entire sub() function before the main() function. That'll work, too.
I am learning C++ and very new at using classes, and I am getting very confused in trying to use them. I am trying to convert my existing code (which used structs) so that it uses classes - so while I know what I am trying to do I don't know if I'm doing it correctly.
I was told that when using functions from the class, I first need to instantiate an object of the class. So what I have tried (a snippet) in my main function is:
int main()// line 1
{
string message_fr_client = "test"; //line2
msgInfo message_processed; //line 3
message_processed.incMsgClass(message_fr_client); //line 4
if (!message_processed.priority_check(qos_levels, message_processed)) //line 5
cout << "failure: priority level out of bounds\n"; //line 6
return 0; //line 7
}
Could you help me clarify if my following assumptions are correct? The compiler is not showing any error and so I don't know if it is error-free, or if there are ones lurking beneath.
At line 4, is the function incMsgClass being performed on the string message_fr_client and returning the resultant (and modified) message_processed?
At line 5, the function priority_check is being performed on the message_processed and returning a boolean?
In my class definition, I have a function getPath that is meant to modify the value of nodePath - is it just a matter of using message_processed.getPath(/*arguments*/)?
I haven't included the body of the functions because I know they work - I would just like to find out how the class functions interact. Please let me know if I can be clearer - just trying to clear up some confusion here.
Here is my class:
#ifndef clientMsgHandling_H
#define clientMsgHandling_H
#include <list>
#include <map>
#include <queue>
class msgInfo
{
public:
msgInfo();
msgInfo(int, int, int, std::string, std::list<int>);
/*classifying message*/
msgInfo incMsgClass(std::string original_msg);
/*message error checks*/
bool priority_check(int syst_priority, msgInfo msg); //check that message is within qos levels
bool route_check(std::map<std::pair<int, int>, int> route_table, msgInfo msg); //check that route exists
void getPath(msgInfo msg, std::map<std::pair<int, int>, int> route_info, int max_hop);
private:
int source_id;
int dest_id;
int priority;
std::string payload;
std::list<int> nodePath;
};
#endif
While it may compile (and even run), there are a few oddities with the code as shown:-
First off, class methods know which object they are operating on - so your priority_check and route_check methods probably don't need msgInfo as a parameter.,
for example, your old non-class function might be like this
bool priority_check(int p, msgInfo msg)
{
return msg.priority < p;
}
But the new one should look like this:
bool msgInfo::priority_check(int p)
{
return priority < p;
}
Also, incMsgClass is a bit odd, as it's a non-static class method that returns a msgInfo object. It's difficult to tell without understanding what it's supposed to do, but it seems possible that this function should actually be a constructor, rather than a regular method.
One other thing is that you're currently passing a msgInfo by value to those methods. So if the method needed to modify the passed msgInfo, it would not have any effect. It's generally better to pass objects by reference or const reference to other methods. So, back to the previous non-method example, it should really be this.
bool priority_check(int p, const msgInfo &msg)
...
But, as I said, you probably don't need the msgInfo parameters anyway.
At line 4, is the function incMsgClass being performed on the string message_fr_client
Yes
and returning the resultant (and modified) message_processed?
Whatever it's returning, you're ignoring the return value. It can modify the object itself, yes, because the function is not const.
At line 5, the function priority_check is being performed on the message_processed and returning a boolean?
Yes
In my class definition, I have a function getPath that is meant to modify the value of nodePath - is it just a matter of using message_processed.getPath(/arguments/)?
If a member function is intended to modify one of the class members, it's just a matter of not marking that function const
Hard to tell without implementation-details, but here we go:
I. You are passing a std::string as value (C++ is call-by-value by default), so you get a copy of the std::string in your method. If you want to work on the object you passed and manipulate it, use a reference on the object, like
msgInfo incMsgClass(std::string& original_msg); // notice the ampersand
then you can change your signature to
void incMsgClass(std::string& original_msg);
as you don't need to return the std::string you passed.
II. Yes, at least according to your signature
III. Can see a node_path only as a member.
For all your questions, see C++-FAQ.
Your basic assumptions are correct.
message_processed.incMsgClass(message_fr_client); //line 4
This line is not correct. The function you call returns msgInfo which is simply dropped. You should assign it to something. But it is not as it is usually done. You should make it a constructor of msgInfo, like
class msgInfo
{
public:
msgInfo(std::string original_msg);
...
}
Then you could call it like this
msgInfo message_processed(message_fr_client);
That line would create a msgInfo that is already properly initialized.
There is another pattern for creating class instances - static creating function. In your case you could mark incMsgClass static and then call it like
msgInfo message_processed = msgInfo.incMsgClass(message_fr_client);
I seriously doubt you need this pattern here, so I'd advise to move to constructor.
As of other functions, I see no problems there. Just note that all member functions not marked as const can modify the object they are called on. So, you don't need to pass this object explicitly. For functions a pointer to the object they are called on is available by name this. Also the functions can access all class variables as if these variables are global for normal (non-member) functions.
I'm getting the titular error, but I can't for the life of me figure out how to resolve it. I've scoured the internet a fair bit, but for the most part I can't find anything that pertains directly to, or solves, the problem I'm having, and all the information I read about anonymous classes, seems to agree with the code I wrote.
The essence of what I'm trying to do is; I have a struct, and I want that struct to contain a function pointer. What I'm having trouble with is when I define an instance of the struct, I'm trying to create and pass an anonymous function to the struct. But it's giving me a compile error.
Anyways, here are the details of the actual problem, the error occurs on this line,
[&](int x) { this->moveLeft(); };
It says "Parse Issue: Expected expression" and points to the ']'
of the following code
Combatant::CharacterData Combatant::characters = {
/*Name */"SomeName",
/*Folder */"SomeFolder",
/*Offense */1.0f,
/*Defense */1.0f,
/*Combos */{
{KeyMemory(KeyMemory::MOVE_LEFT, KeyMemory::JUMP),
[&](int x) { this->moveLeft(); };
},
{KeyMemory(KeyMemory::MOVE_LEFT, KeyMemory::JUMP),
[&](int x) { this->moveLeft(); };
}
}
}
The CharacterData struct is defined by this code:
struct Combo {
KeyMemory controls;
void (*execute)(int);
};
struct CharacterData {
std::string name;
std::string folder;
float offense;
float defense;
Combo comboList[5];
};
Any help, would be much appreciated. ^_^
You might need to use a std::function<void(int)> to hold your lambda. (Particularly since you are using [&]).
Also, I'm not sure [&] actually makes sense in a global context. Maybe you should be passing in the object to call moveLeft on, and using []. Also, that change might let you use your simple function pointer instead of a std::function.
The problem turned out to be that Clang, which is the compiler used by Xcode/Apple doesn't yet support lambda functions. From what I read however the feature is coming in the future.
/* Thanks to anyone looking at this who might attempt to answer it. I'm really not trying to waste anyone's time here, but I have beat my head on this for about three days. I realize it is probably very simple for someone who understands it. I have tried most every possible combination I can think of and still get compiler errors.
C:\random\RNDNUMTEST.cpp(41) : error C2102: '&' requires l-value
I am trying to pass a pointer as a parameter to a function makeRndmNumber() for the member function fstream.open(). I want to open the file in RNDNUMTEST.cpp and then pass it to makeRndmNumber() so that it can be modified in some way. I have looked online for help, including this website, but I feel like I am overlooking something important or simple or maybe I am just missing the concept altogether.
This isn't for homework, I'm not a college student. Although I did go to school for it, it has been over 10 years since I've done any programming and I never really understood this that well to begin with. Any suggestions would be appreciated.
// These are only excerpts from the actual files.
// RndmNum_Class.h file
typedef void(fstream::*fStream_MPT)(const char*); // fStream_MPT (Member Pointer Type)
class RandomNumber {
public:
RandomNumber();
~RandomNumber() {};
static void loadDigits(double, double, char array[]);
static int getLastNDigits(char array[], int);
static int makeRndmNumber(int, int, fStream_MPT);
};
//*************************************************************8
//RndmNum_Class.cpp file
int RandomNumber::makeRndmNumber(int seed, int _fileSize, fStream_MPT FILE) {
......
}
//**************************************************************/
// RNDNUMTEST.cpp file
#include "RndmNum_Class.h"
int main() {
const char* RNDM_FILE = "c:\\RandomFile.txt";
fstream FStream_Obj;
// FStream_Obj.open(RNDM_FILE);
fStream_MPT FileMembPtr = &FStream_Obj.open(RNDM_FILE);
//fStream_MPT FileMembPtr = &fstream::open;
int seed = 297814;
int size = 20000;
cout << RandomNumber::makeRndmNumber(seed, size, FileMembPtr);
return 0;
}
This: &FStream_Obj.open(RNDM_FILE) is not taking the address of the function, it's trying to take the address of the return value of a call to that function. But that function returns void, hence the error message.
First, change the function definition from typedef void(fstream::*fStream_MPT)(const char*); to typedef void(fstream::*fstream_MPT)(const char*,ios_base::openmode), there is a default parameter you are forgetting.
Change the fStream_MPT FileMembPtr = &FStream_Obj.open(RNDM_FILE); to fStream_MPT FileMembPtr = &fstream::open; as per your comment, and add an additional parameter to makeRndNumber, a pointer to an fstream to operate on.
int RandomNumber::makeRndmNumber(int seed, int _fileSize, fStream_MPT FILE, fstream *file)
{
((*file).*FILE)("ExampleText",ios_base::in | ios_base::out);
}
FILE = fstream::open;
EDIT
This could also be done a little cleaner with std::function objects.
First redefine your type.
typedef std::function<void(const char*)> fStream_MPT;
Then when you assign, be sure to bind your objects.
fStream_MPT FILE = std::bind(&fstream::open,&file,std::placeholders::_1, ios_base::in | ios_base::out);
Then in your function you simply call the function
int RandomNumber::makeRndmNumber(int seed, int _fileSize, fStream_MPT FILE)
{
FILE("Example text");
}
It doesn't make any sense: member function pointers is used so you can apply different member functions somewhere without knowing which exact function is called. It is like passing the function's name around (except that the name is resolved at compile-time). It doesn't seem that this is what you want to do!
Even if you would correctly obtain the function's address (rather than trying to get the address of the result of calling open()), it wouldn't work because std::fstream::open() takes two arguments: the second argument is for the open-mode and it is defaulted to std::ios_base::in | std::ios_base::out.
I'm not quite sure what you really want to d but it seems you want to pass the file stream around. The normal way to do this is to pass a reference to a std::iostream as argument to the function. Well, actually you probably want to use a std::ifstream initially and hence pass the argument as std::istream&.
This c++ code is working fine , however memory validator says that I am using a deleted pointer in:
grf->filePath = fname; Do you have any idea why ? Thank you.
Dirloader.h
// Other code
class CDirLoader
{
public:
struct TKnownGRF
{
std::string filePath;
DWORD encodingType;
DWORD userDataLen;
char *userData;
};
// Other Code
CDirLoader();
virtual ~CDirLoader();
Dirloader.cpp
// Other code
void CDirLoader::AddGroupFile(const std::string& _fname)
{
// Other code including std::string fname = _fname;
TKnownGRF *grf = new TKnownGRF;
grf->filePath = fname;
delete grf; // Just for testing purposes
P.S.: This is only an code extract. Of course if I define a struct TKnownGRF inside .cpp and use it as an actual object, gfr.filepath = something, instead of pointer grf->filepath=something, than it is ok, but I do need to have it inside *.h in CDirLoader class, due to many other vector allocations.
Since the function returns void
void CDirLoader::AddGroupFile(const std::string& _fname)
the question is what are you going to do with grf?
Are you going to delete it? If so, then, why do a new? you can just declare a TKnownGRF variable on the stack! In that case, _fname is not contributing to the logic of this method.
I guess that the class CDirLoader has a member variable of type TKnownGRF, say grf_, and that need to be used in the AddsGroupFile() method, e.g.:
grf_.filepath = _fname;
Does this happen to be using an older version of STL, say, VC6, and running multithreaded? Older versions of STL's string class used a reference counted copy on write implementation, which didn't really work in a multithreaded environment. See this KB article on VC 6.
Or, it's also possible that you are looking at the wrong problem. If you call std::string::c_str() and cache the result at all, the cached result would probably be invalidated when you modified the original string. There are a few cases where you can get away with that, but it's very much implementation specific.