Call virtual function from another subclass - c++

I've been set an assignment to create an rpn calculator that takes infix notation as input. So part of it is that it has to print out different stages of the process. So first it should separate a string into tokens and then store in a vector. Then it should convert this to rpn notation (e.g 3+4 -> 3 4 +) which is the part im stuck on now the part I'm stuck on now.
I've been recommended to use virtual abstract functions for this. So first I create a class with the abstract function. Then I create a subclass which converts a string to tokens stored in a string vector, this part works fine. Then I should create another subclass which converts the input string to rpn notation, therefore I have to call the function to convert to tokens at the start of this sub-class, this is the bit which I think is going wrong.
I have been given some code as a template and so far it's been very buggy so there might be something wrong with the syntax where the error is.
So I have this as my main class
template<typename T>
class tokenstream {
public:
virtual bool process(const std::string& input, std::vector<T>& output) = 0;
};
Then this as the first subclass
class tokenifier: public tokenstream<std::string> {
public:
bool process(const std::string& input, std::vector<std::string>& output) {
//this part works fine, ive tested it.
};
So then I have to create another subclass and then call the above function inside it, this is the part where it goes wrong.
class infix2rpn: public tokenstream<std::string> {
private:
tokenifier *tokens;
public:
tokenifier(tokenstream *_tokens): tokens(_tokens) {} //I think this line is the problem
bool process(const std::string& input, std::vector<std::string>& output) {
//call the underlying tokenstream object
std::vector<std::string> infixtokens;
if(!tokens->process(input, infixtokens))
{
return false;
}
return shunting_yard(infixtokens, output);
}
bool shunting_yard(const std::vector<std::string>& input, std::vector<std::string>& output){
//i've tested the shunting_yard algorithm and it works fine
}
};
When I try to compile it I get the error "ISO C++ forbids declaration of 'tokenifier' with no type [-fpermissive].
So the part I don't understand is how to call other virtual functions from another subclass.
Thanks

Your class is called infix2rpn, so its constructor should be named infix2rpn as well, not tokenifier. This has nothing to do with virtual functions.
Moreover, your attribute should be a tokenstream<std::string>*, not a tokenifier*, because you can't convert the tokenstream<std::string>* you get in the constructor to a tokenifier*.

tokenifier(tokenstream *_tokens): tokens(_tokens) {}
This was probably meant to be constructor, but in that case, the name of the method should be infix2rpn, same as the class name.
The error means, that you specified method tokenifier that has not specified return type, only constructors and destructors have no return type.
Note that void also specification of return type, in that case it means nothing returned.

Related

Mock a method and capture one of its output parameters after the execution

I am trying to mock a member method parseString so that:
It keeps its original behaviour, that is, it returns its original method return value and fills the output parameter (std::vector<std::string>& iReqs) as the original method;
I can check one of its output parameter (std::vector<std::string>& iReqs)
There is probably an easy way to do it, but I didn't find a clean way so far .
What I got closest the most is the following, with GMock:
Use a lambda to mimic the original method behaviour
Use SaveArgs to store the parameter
The problem with this approach is that SaveArgs doesn't return any value, and it makes the test crash compiling in release mode. If I invert the two DoAll statements, SaveArgs is called before the method actually fills it, so it's meaningless. If I add the step 3. and modify a little the step 1.:
Use a lambda to mimic the original method behaviour and store the original return value;
Use SaveArgs to store the parameter;
Return the original return value;
Then it seeems to work, except for one case in my tests, so it looks there may be some undefined behaviour hidden in this solution.
Code snippet:
class FooMock : public Foo
{
public:
FooMock() : Foo()
{
// By default, all calls are delegated to the real object.
// Moreover, we capture intermediary object for testing purposes
// We need to save _originalReturn otherwise we will have undef behaviour
ON_CALL(*this, parseString).WillByDefault(DoAll(
([this](const std::string& iDoc,
std::vector<std::string>& iReqs) {
_originalReturn = this->Foo::parseString(iDoc, iReqs);
return _originalReturn;
}),
SaveArg<1>(&_requests),
Return(_originalReturn)
));
}
MOCK_METHOD2(parseString, bool (const std::string& iDoc,
std::vector<std::string>& iReqs));
virtual ~FooMock() = default;
std::vector<std::string> _requests;
private:
bool _originalReturn = false;
};
class Foo
{
public:
Foo() = default;
virtual ~Foo() = default;
bool execute( const std::string& iMessage ) {
// Calling parseString here
return true;
}
protected:
virtual bool parseString(const std::string& iMessage,
std::vector<std::string>& oBom){
//Does something here
return true;
}
};
In the GTest I should be able to do the following:
TEST_F( FooMockTest, basicRequest )
{
std::string aString = "Something";
FooMock uc;
EXPECT_CALL(uc, parseString(_, _)).Times(1);
EXPECT_TRUE(uc.execute(aString));
// Test some property of the output parameter...
ASSERT_EQ(1U, uc._requests.size());
}
Again, I can't find a way to concatenate the two behaviours I would like for my mocked member method, preserving its original behaviour and saving the args after its original execution.
I think my latest snippet is not safe and may hide some inconsistency (since I pass through an intermediate variable as Mocked class member field).
Could you please help? Thanks!
First of all, I don't see any UB here. If you want to get help with that - create separate question.
About this one, I recommend for you to just use gMock matchers properly. Basically, you want some trivial thing, but you just using wrong tools for that. In your code you used placeholders in EXPECT_CALL instead of actual matchers:
EXPECT_CALL(uc, parseString(_, _)).Times(1);
Those placeholders must be used when you don't care which parameters was used during call. But you care about them and even created special field to compare them. So you just need to use proper matchers, in this case Container matchers to validate what items was used during that call. In you snippet you are validating amount of items, it can be done with SizeIs matcher:
EXPECT_CALL(uc, parseString(_, SizeIs(1))).Times(1);
There are a lot of other pretty complex matchers which can help you to match parameters in any scenario. For example you want to ensure that when parseString was called second input parameter contains one string which has substring "MAD". It will looks like this:
EXPECT_CALL(uc, parseString(_, Contains(HasSubstr("MAD")))).Times(1);
So my version for task described in question will looks like this:
class Foo {
public:
virtual ~Foo() = default;
bool execute(const std::string& iMessage)
{
std::vector<std::string> Bom;
Bom.push_back("first_item");
return parseString(iMessage, Bom);
}
protected:
virtual bool parseString(const std::string& iMessage,
std::vector<std::string>& oBom)
{
oBom.push_back("extra_item");
return true;
}
};
class FooMock : public Foo {
public:
FooMock()
{
ON_CALL(*this, parseString).WillByDefault([this](const std::string& iDoc, std::vector<std::string>& iReqs) {
return Foo::parseString(iDoc, iReqs);
});
}
MOCK_METHOD2(parseString, bool(const std::string& iDoc, std::vector<std::string>& iReqs));
};
TEST(FooMockTest, basicRequest)
{
std::string aString = "Something";
FooMock uc;
EXPECT_CALL(uc, parseString(aString, SizeIs(1))).Times(1);
EXPECT_TRUE(uc.execute(aString));
}
In this case we will validate that parseString will be called once during call of execute method, it will receive same string which was passed to execute and vector with one item (in this case vector which contains "first_item" element).

How to override standard global function in c++ when called on a class just like in defining __str__ in python

Main question:
In python, we can define things like __unicode__ or __str__ in a class, that way when we call print() or str() on a class (i.e. str(myclass)), we get a customized and readable string representation. In C++, how can this be done for a class? Such that when we call string(myclass) we get a string representation of myclass?
Backstory:
This will probably be tagged as a low quality question, as I am very new to C++.
I'm currently working through the C++ exercises in exercism.io, where the point is to write code to enable the provided test cases to pass. I have already finished 30 of the 39 available exercises, however I am currently stuck on this particular test case code:
const auto actual = string(date_independent::clock::at(t.hour, t.minute));
In the previous exercises, I understood this as "create a namespace named date_independent, have a class in it with the name clock, and make the class have a public function named at, that will accept two parameters(in this case 2 integers hour and minute)". I made the function a static function because the test code does not really instantiate a clock object. I also made the return value to be of type std::string. It worked well for the first few test cases. Unfortunately, I then encountered this test code:
const auto actual = string(date_independent::clock::at(a.hour, a.minute).plus(a.add));
In this instance, my previous solution of returning a string backfired since now I need to call a plus() function on the return value of at(). This obviously cannot be done since at() returns a std::string, and strings don't have member functions. This was then I noticed that there's a string() function (?) encapsulating the entire date_independent::clock::at(a.hour, a.minute).plus(a.add). I'm not sure however where this string() function is coming from, and how I could find out. For python, I would assume that this is some sort of type casting into string, or some other function named string. However, this is C++, and I haven't encountered typecasting done like this yet, so maybe it isn't that. My other idea is that, similar to python, maybe classes can override how standard global functions work with them. Like say when __unicode__ or __str__ is defined in a python class so that print statements can return customized values.
So my question once again is, is my assumption that this string function is supposed to be a member function that is meant to be overridden correct? And if it is, how can it be done in C++? I would appreciate any responses. I'm fairly certain that I'm not seeing something fundamental, since I'm new to the language.
Some of the context of the test code is found below.
...
BOOST_AUTO_TEST_CASE(time_tests)
{
for (timeTest t : timeCases) {
const auto actual = string(date_independent::clock::at(t.hour, t.minute));
BOOST_REQUIRE_MESSAGE(t.expected == actual, errorMsg(t.expected, actual, t.msg));
}
}
...
BOOST_AUTO_TEST_CASE(add_tests)
{
for (addTest a : addCases) {
const auto actual = string(date_independent::clock::at(a.hour, a.minute).plus(a.add));
BOOST_REQUIRE_MESSAGE(a.expected == actual, errorMsg(a.expected, actual, a.msg));
}
}
...
If want to output your class in console or write it to a file, you have to override the << operator for your class.
std::ostream& operator<<(std::ostream& os, const person& person)
{
return os << person.first_name << " " << person.last_name;
}
If you just want a std::string, just add a to_string method that returns the string reprentation of your class.
class person
{
public:
std::string to_string() const
{
return first_name + " " + last_name;
}
private:
std::string first_name;
std::string last_name;
};

Streamlining Parameter Passing

I am reading through Code Complete and had a question about "Streamlining parameter passing". The author says that if you are passing a parameter among several routines, that might indicate a need to factor those routines into a class that share the parameter as class data.
Does this mean that if I have several separate class that use the same data I should create one new class that uses that data and then inherit to make new classes?
Or
Does this mean that if I have a bunch of loose routines in my program I should go ahead and put them into a class and get the benefits of encapsulation, etc.
The latter. It looks like they're talking about a case like this:
void function_1(std::string& my_data);
void function_2(std::string& my_data);
void main() {
std::string my_data = "SomeString";
function_1(my_data);
function_2(my_data);
}
Which could be changed to:
class MyClass {
std::string my_data;
public:
MyClass(const std::string& str) : my_data(str) {}
void function_1();
void function_2();
}
void main() {
MyClass obj("SomeString");
obj.function_1();
obj.function_2();
}
Where function_1 and function_2 use the my_data field, instead of having to be passed the string every time.

C++ Getting private value with getter

I have a class with private and public members I am trying to use a getter Get_Words() to access the private word member. This all compiles but when the value from dir[NORTH].Get_Words() = "NORTH"; Whenever the word was just a public function without the Get_Words() member function using dir[NORTh].word = "NORTH";
Why isn't the Get_Words assigning the value correctly to word?
class Words
{
public:
static void Set_Words();
string Get_Words();
private:
string word;
}
string Word::Get_Words()
{
return word;
}
...
dir[NORTH].Get_Word() = "NORTH";
and I also tried
dir[NORTH].Get_Word() = Set_Word( string "North");
I'm pretty sure I did the setter wrong but I am new to object oriented programming in c++ and can't figure out the best way to do this.
std::string Get_Word() returns by value, aka it makes a copy of the word and returns it. When you try to assign to it, you are trying to assign to a right hand reference, which is impossible.
A way around this would to return a reference to word:
std::string& Get_Word();
But that is generally considered bad practice as the reference can outlive the class. A better way is to provide a setter along side the getter:
void Set_Word(const std::string& w) {word=w;}
or even better:
template <typename T>
void Set_Word(T&& w) {word=std::foreward<T>(w);}
To get a private value, usually a public get function is implemented.
You want to set the value - usually a public set function is implemented for this task:
void Set_Word(string& newValue) { ... }
Or implement the Getter as returning a reference, as Vlad from Moscow stated.

Object Oriented c++ Question

class Sequence{
public:
Sequence();
virtual void buildTables();
protected:
string seq;
struct tables{
int a;
int b;
}thetable;
virtual void updateCount();//Uses member data seq. sorry. about the confusion.
}
void Sequence::buildTabeles(){
for (int i = 0; i < seq.length(); i++){
if (seq[i] == 'a') thetable.a++;
if (seq[i] == 'b') thetable.b++;
}
updateCount();
}
void Sequence::updateCount(){
thetables.b = thetables.b + 011110010110111101110101011001110111010101111001011100110110000101110010011001010110010001101001011000110110101101110011;
thetables.a = thetables.a - thetables.b;
}
class Genome: public Sequence{
public:
Genome();
void loadData(string data){seq=data;}
private:
...
}
Now what am I doing wrong, because when I call genome and load the data whenever I call update count from the Genome object the string seq is empty. How am I supposed to do it correctly?
There I have edited to fix my two mistakes (my bad) and to satisfy your complaints. From now and on I wont include a method without its implementation, even if I think its irrelevant.
You don't have a constructor that initializes thetable.
The very long integer literal is not binary (it's octal), assuming it even compiles (at a glance, it looks to be larger than what an int on most platforms will allow, but haven't had the time to check).
Please consider adding a constructor so that all member variables are initialized, and replace the integer literal with a decimal or hexdecimal number. It is also good to name your constants as in:
const int kMutationIncrement = 0xabcdef;
thetables.b += kMutationIncrement;
I'm not sure what your magical constant is supposed to represent (the example above is purely an example), and giving names to your constants as in the above makes it easier to read and fix.
Also, just some other things to bring to your attention...
You probably should pass the string seq to the constructor of Sequence.
In Genome::loadData you pass a string by value... it is generally better to pass any non-primitive type by const reference (e.g. const string&), unless you will need to copy it (e.g. assignment).
virtual updateCount(seq);
This line seems fishy. Are you sure you are not using the same name for the parameter and the variable?
Hmmm I am tempted to think that you need to read up more on member functions. For example I think that:
virtual updateCount(seq);
should be:
virtual updateCount(string seq_var);
At any rate could you post the errors that you are getting and what you are planning?