Trying to implement polymorphism with objects [duplicate] - c++

This question already has an answer here:
C++ Forward Declaration confusion
(1 answer)
Closed 5 years ago.
I'm trying to implement polymorphism, as can be seen by the code below. I want vector of expressions of type class expression. these expressions will have a right and left parameter object of type Parameter class. As it may have been guessed, this could recurse until one hits a string "a_string" or "an_id." However, the compiler doesn't, first of all, know what type "Expression" is for the vector. Any help is needed. Thank you.
#ifndef PARAMETER_H
#define PARAMETER_H
#include <string>
#include <vector>
using namespace std;
class Parameter
{
private:
string a_string;
string an_id;
vector<Expression> expressions;
public:
Parameter(bool expr_stringID);
};
class Expression : public Parameter
{
private:
Parameter left_parameter;
Parameter right_parameter;
char op;
public:
};
#endif

Poymorphism either requires virtual functions (at least a virtual destructor), or the CRTP to realize Static Polymorphism.
You provide neither of these with your example.

Related

What is the difference when generic class is declared with and without using default constructor? [duplicate]

This question already has an answer here:
constructor without parameters doesnt work but one with does work [duplicate]
(1 answer)
Closed 2 years ago.
I have a generic class defined down below,
with member parameter an array, i.e. T grades[5];
when I declare object of this class, using
StudentRecord<int> srInt();
and then call a member function of the class, using
srInt.setGrades(arrayInt);
I get an error,
error: request for member ‘setGrades’ in ‘srInt’, which is of non-class type ‘StudentRecord<int>()’
srInt.setGrades(arrayInt);
but when i declare class using(below), and try to call same function, it works
StudentRecord<int> srInt;
//header file for main.cpp
#include<iostream>
using namespace std;
const int SIZE=5;
template <class T>
class StudentRecord
{
private:
const int size = SIZE;
T grades[5];
public:
void setGrades(T* input);
};
template<class T>
void StudentRecord<T>::setGrades(T* input)
{
for(int i=0; i<SIZE;++i)
{
grades[i] = input[i];
}
}
My question is there any difference between declaring class,
StudentRecord<int> srInt();
v/s
StudentRecord<int> srInt;
This is not about templates ("generic class").
Just like int f(); is a function declaration, StudentRecord<int> srInt();s is a function declaration. Yes, even when you write it in a function.
Remove the () and you get an object declaration instead.
That's it!
Some people call this the "Most vexing parse", though it is not actually an example of that. It does involve some of the same grammar/language rules to a degree.
When you wrote StudentRecord<int> srInt(-1);, that is a valid object declaration, because there is no way it can be a function declaration (-1 is not an argument declaration).
If -1 were swapped for a more complex expression, it's possible to get surprised by the fact that it gets interpreted as a valid argument declaration. Like int f(int());. That's the most vexing parse.
There's no magic or strangeness here; you just have to use the right symbols for what you want.

Scope and inheritance in c++ [duplicate]

This question already has answers here:
automatically convert list of pointers to derived class to list of pointers to base class
(4 answers)
Closed 4 years ago.
I would like to know why the compiler doesn't allow the second use of "print_all" function.
I have to give an example of a bad thing that could happen if the compiler would allow it.
#include <iostream>
#include <list>
using std::list;
class foo {
class bar : public foo {
static void print_all(list<foo *> &L) {
list<foo *> LF;
list<bar *> LB;
print_all(LF); // works fine
print_all(LB); // static semantic error
}
};
};
list<foo *> is an unrelated type to list<bar *>. The function is specified to accept one, but not the other.
But class bar inherits from class foo
That is irrelevant, because the argument of your function isn't foo&. What's relevant is whether list<bar *> inherits list<foo *>. It doesn't. std::list does not have a base class.

Map of pointers to member functions in another class [duplicate]

This question already has answers here:
Using generic std::function objects with member functions in one class
(6 answers)
Closed 7 years ago.
I know, that this question was already asked here, but I believe that my particular example is unique:
#include <functional>
#include <map>
#include <vector>
class Bar{
public:
static unsigned myFunc(const std::vector<std::string> &input){return 1;};
};
class Foo{
friend class Bar;
public:
using CommandFunction = std::function<unsigned(const std::vector<std::string> &)>;
std::map<std::string, CommandFunction> Commands;
};
int main(){
Foo oFoo;
Bar oBar;
oFoo.Commands["myFunc"] = oBar.myFunc;
return 0;
}
I want to make the myFunc function non-static, so it will be able to access private members of the Bar class. But I have no clue how to implement this idea. Simply removing the static keyword obviously will raise an error during compilation (invalid use of non-static function). Is there any 'clean' way of solving this problem? And by 'clean' I mean not using global variables and objects.
Update
I think I need to clarify the purpose of the design I described above.
I'm using a wrapper to the GNU readline library. It is represented by the Foo class. Basically it holds a set of function pointers inside the Commands map and executes them based on the user input.
The Bar class is a set of functions which share common resources (private members of the Bar class).
Lambda could be a solution for you:
class Bar{
public:
std::function<unsigned(const std::vector<std::string>&)> myFunc{ [](const std::vector<std::string>& x){return 1;}};
};

stack variable or declaration of function [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Most vexing parse: why doesn't A a(()); work?
I have two classes in file1.h:
class ZoneRecord {
public:
//a lof of stuff here
};
class RegisterRecord {
public:
RegisterRecord(ZoneRecord rec); //this function register object rec in a fabric
};
And file2.cpp has:
#include "file1.h"
class MockZoneRecord: public ZoneRecord {
public:
MockZoneRecord(): ZoneRecord() {}
};
RegisterRecord mockrecord_register(MockZoneRecord());
This code compiles perfectly, except one thing. It says that mockrecord_register is a declaration of a function. But I actually wanted to create an global object of type RegisterRecord with name mockrecord_register. How to explicitly tell to compiler that this is not a function prototype, but an object?
You are experiencing the most vexing parse.
One way to solve this is to use copying, like
RegisterRecord mockrecord_register = RegisterRecord(MockZoneRecord());
Another is the use of parenthesis like in the answer by yuri kilochek.
If your compiler is C++11 compatible, you could use this construct:
RegisterRecord mockrecord_register{MockZoneRecord()};
Place parenthesis around argument:
RegisterRecord mockrecord_register((MockZoneRecord()));

C++: Templates of child classes only [duplicate]

This question already has answers here:
Restrict C++ Template Parameter to Subclass
(8 answers)
Closed 7 years ago.
Is there any way to make a template only work with child classes of a base class? Something like this:
template<BaseClass T>
class FooBar
{
// ...
};
Either use a static assert from your favourite C++ library (such as this boost example), or put a call in the constructor (or other code which will always be generated when the code is used) to a do-nothing function taking a BaseClass type, for example:
template<class T>
class FooBar
{
public:
FooBar () {
Check(static_cast<T*>(0));
}
private:
void Check ( BaseClasse* ) {}
};
(not tested)
Not directly, but you can test it in the constructor using Boost:
#include <boost/type_traits/is_base_of.hpp>
#include <boost/static_assert.hpp>
template<class T>
class FooBar{
FooBar(){
BOOST_STATIC_ASSERT(boost::is_base_of<BaseClass,T>::value);
}
};
Or if you don't want a static assert, something like this is also nice sometimes:
typedef char ERROR_T_must_be_derived_from_BaseClass[boost::is_base_of<BaseClass,T>::value ? 1 : -1];
Since whoever compiles your code will be brought to this line and has a "readable" error message.
There are ways to make it work with a static assert. See Boost.StaticAssert