Delegate in c++ (or something like this) - c++

In C++, i have:
//Base1.h
#ifndef BASE1_H
#define BASE1_H
#include <iostream>
#include <string>
#include "Base2.h"
using namespace std;
class Base1{
private:
string name;
public:
Base1(string _name);
void printSomething();
string getName();
};
#endif
In Base1.cpp i implement constructor Base1(string _name) and string getName() as normal, and the printSomething():
void Base1::printSomething(){
Base2 b2;
// how to pass a parameter in the following code?
b2.printBase1();
}
// This is Base2.h
#ifndef BASE2_H
#define BASE2_H
#include <iostream>
#include <string>
#include "Base1.h"
using namespace std;
class Base2{
public:
Base2();
void printBase1(Base1 b);
};
#endif
And Base2() constructor i implement as usual, this is my printBase1(Base1 b):
void Base2::printBase1(Base1 b){
cout << b.getName();
}
So, in the end, i want to use printSomething() in Base1 class, but i don't know how to pass parameter to the b2.printBase1() in printSomething() as above in my code. is there anything like b2.printBase1(this) in C++? If not, can you give me a suggestion?

Since this is a pointer in C++, you need to dereference it:
b2.printBase1(*this);
Note that you have circular includes, you should remove #include "Base2.h" from Base1.h. Also look into passing parameters by (const) reference, especially for non-POD types, otherwise you might not get the expected behavior.
For example, your signature is
void printBase1(Base1 b);
when you call it, you create a copy of the parameter in the function, and thus operating on a copy. You should change this to:
void printBase1(Base1& b);
or
void printBase1(const Base1& b); //if you don't change b
Pass by value only when you're certain you need a copy.

Related

Getting 'undeclared identifier' when using vector of type class

Having trouble understanding why I'm getting an 'undeclared identifier' error when I've made sure to include the header file that has the declaration of the class I'm making a vector of.
#pragma once
#include <vector>
#include "Member.h"
class Party {
private:
std::vector<Member> members;
public:
Party();
int get_party_size();
void add_member(Member new_member);
Member& get_member(int num);
};
Here's "Member.h"
#pragma once
#include <vector>
#include <string>
#include "Party.h"
class Member
{
private:
int hp;
bool is_stunned;
bool is_alive;
public:
Member();
~Member();
int get_hp();
bool get_is_stunned();
bool get_is_alive();
void take_damage(int amt);
void stun();
virtual void turn(std::vector<Party>& parties, int my_party, int my_member_number);
virtual std::string get_class_name();
};
Pretty new to the language, so sure I'm missing something obvious.
You have circular dependency between Member and Party
Remove the line
virtual void turn(
std::vector<Party>& parties,
int my_party,
int my_member_number);
in Member and remove the #include "Party.h" in Member.h
Instead think along the lines that a Party is just a collection of Members so there is no need for an individual Member to know about the container
So after input from #some-programmer-dude you could also solve it by adding a forward declaration in your Member.h instead of including the Party.h
class Party;
class Member { ... }

Calling a function from another class from within an unordered_multimap?

This is related to my last post that you can find here: Creating an unordered_map of std::functions with any arguments. I have now gone ahead and extended this out to classes. So let's say I have three different classes. And these classes all have different methods except for getVariable() and setVariable(int). So for this example we will class them ClassA, ClassB, and ClassC.
I also have a base class which I want to use as my driver. Essentially, if I want to set the variable between ClassA and ClassC I would call the base class' setVariable function.
#ifndef BASE_CLASS_HPP
#define BASE_CLASS_HPP
#include <unordered_map>
#include <functional>
#include <utility>
#include <string>
#include <any>
template<class A, class B>
class BaseClass
{
public:
BaseClass() { bindThem(); }
std::pair<int,int> getValue()
{
// return classA and ClassB's values
}
void setValue(int newVal)
{
auto iter = functions.equal_range("setValue");
std::any_cast<void(*)(int)>(mapIter->second)(newVal);
}
private:
std::unordered_multimap<std::string,std::any> functions;
void bindThem()
{
functions.emplace("setValue",&A::setValue);
functions.emplace("setValue",&B::setValue);
functions.emplace("getValue",&A::getValue);
functions.emplace("getValue",&B::getValue);
}
};
I then have in main:
#include <iostream>
#include "baseClass.hpp"
#include "classA.hpp"
#include "classB.hpp"
#include "classC.hpp"
int main()
{
ClassA a;
ClassB b;
ClassC c;
c.setValue(20);
BaseClass<ClassA,ClassB> base1;
BaseClass<ClassA,ClassC> base2;
base1.setValue(15);
auto values = base1.getValues();
}
I can place the functions withing my map, however, when I try to any_cast I don't get anything in return. I also tried:
std::any_cast<void(A::*)(int)>(mapIter->second)(newVal);
But that also gives me a compiler error of must use .* or ->* and I have tried everything to get it to compile and I don't really know what I am doing wrong. I also realized, if I called it that way, then I wouldn't be able to access B's setVariable function since I am using A's namespace.
Is there anyway I can get this to work how I want it to? I am essentially trying to modify those class values without having to make any copies of those classes and instead directly modify them from within this driver.
I still don't quite understand the purpose of such structure, but here an option how to make it at least compile:
#include <unordered_map>
#include <functional>
#include <utility>
#include <string>
#include <any>
template<class A, class B>
class BaseClass
{
public:
BaseClass() { bindThem(); }
std::pair<int,int> getValue()
{
auto range = functions.equal_range("getValue");
return
{
(a.*std::any_cast<int(A::*)()>(*range.first))(),
(b.*std::any_cast<int(B::*)()>(*range.second))()
};
}
void setValue(int newVal)
{
auto range = functions.equal_range("setValue");
(a.*std::any_cast<void(A::*)(int)>(*range.first))(newVal);
(b.*std::any_cast<void(B::*)(int)>(*range.second))(newVal);
}
private:
std::unordered_multimap<std::string,std::any> functions;
void bindThem()
{
functions.emplace("setValue",&A::setValue);
functions.emplace("setValue",&B::setValue);
functions.emplace("getValue",&A::getValue);
functions.emplace("getValue",&B::getValue);
}
A a;
B b;
};
class ClassA
{
public:
void setValue(int){}
int getValue() {return 0;}
};
class ClassB
{
public:
void setValue(int){}
int getValue() {return 1;}
};
int main()
{
BaseClass<ClassA, ClassB> x;
x.setValue(3);
auto i = x.getValue();
}
Please note several things:
I've added members to BaseClass since to call member functions you need an object to be called on.
I'm using first and last iterators of the range from equal_range, but the order of elements in that range is implementation defined. So to make things work you need to take care of distinguishing which container element corresponds to class A and which to class B.

Error in initializing new object in other class using "this" pointer of the other

I have two classes: SessionCardsMode and SetOfCards. SessionCardsMode takes in its constructor pointer to object of SetOfCards. When I try to create dynamically new SessionCardsMode object in SetOfCards method initializing it with this pointer I get information: "Cannot initialize type 'SessionCardsMode' with rvalue of type 'SetOfCards*'". It looks like I haven't proper constructor, but I have provided it. I don't know why it doesn't work. The problem is in SetOfCards::getSessionCards method in the first line of it. I've found that if I try to create the same object in body of class SessionCardsMode using identical statement everything works fine, but if I try to make it out of class I get the error.
//////////////////////////////SesionCardsMode.h
#pragma once
#include "Card.h"
#include "SetOfCards.h"
class SessionCardsMode
{
protected:
SetOfCards* m_setData;
std::forward_list<Card*> m_sessionSet;
public:
explicit SessionCardsMode(SetOfCards* set) : m_setData(set) {};
virtual Card* getCard();
//allows making combination of set setup by mixing classes that derives
//from ModeOfSet
void addAndShuffle(const SessionCardsMode* mode);
};
///////////////////////////////SetOfCards.h
#pragma once
#include "Card.h"
#include "SessionCardsMode.h"
class SetOfCards
{
private:
std::vector<Card> m_cardSet;
std::string m_setName;
public:
SetOfCards()=default;
explicit SetOfCards(std::string setName);
template<typename Iter>
SetOfCards(Iter begin, Iter end, std::string setName);
SessionCardsMode* getSessionCards(std::vector<CreatorAndInitVal> creators);
};
////////////////////////////////////////SetOfCards.cpp
#include "SetOfCards.h"
SessionCardsMode* SetOfCards::getSessionCards(
std::vector<CreatorAndInitVal> m_sessionCardsCreators)
{
SessionCardsMode* sessionCards=new SessionCardsMode(this); // error here
return sessionCards;
}
I don't understand why you don't get an error when you declare the constructor of SessionCardsMode (when you are compiling SetOfCards.cpp) - as far as I can see, at that point, SetOfCards is not defined.
Anyway, the solution to your problem is not to #include any of the headers in other headers, but to declare (not define) the other classes. So:
//////////////////////////////SesionCardsMode.h
#pragma once
class Card;
class SetOfCards;
class SessionCardsMode
{
protected:
SetOfCards* m_setData;
std::forward_list<Card*> m_sessionSet;
public:
explicit SessionCardsMode(SetOfCards* set) : m_setData(set) {};
...
};
///////////////////////////////SetOfCards.h
#pragma once
class Card;
class SessionCardsMode;
#include <vector> // You need this
#include <string>
class SetOfCards
{
private:
std::vector<Card> m_cardSet;
std::string m_setName;
public:
SetOfCards()=default;
explicit SetOfCards(std::string setName);
...
};
////////////////////////////////////////SetOfCards.cpp
#include "SetOfCards.h" // This should always be first
#include "..." // You'll probably need some more here.
SessionCardsMode* SetOfCards::getSessionCards(
std::vector<CreatorAndInitVal> m_sessionCardsCreators)
{
SessionCardsMode* sessionCards=new SessionCardsMode(this); // Error should be fixed
return sessionCards;
}

invoke object c++. Reflection in c++

I am new to C++ and I'm trying to implement Reflection.
I have a Method class, Field class, and Object class.
Say, that I have an Object of Class Male called Daniel.
The class Male has a method called increaseAge() which increases Daniel's age by 1.
Daniel has an int field - age.
How do I invoke the Method increaseAge() on Daniel.
typedef void(*Func)(Object*);
class Method{
private:
std::string nameMethod;
Func f;
public:
Method(std::string name,Func fun){
nameMethod=name;
f=fun;
};
/*virtual void invoke(Object* const obj);
if Object has method, then invoke method on obj.
else > throw MethodNotFound.
*/
};
#endif /* METHOD_H_ */
and, my main.cpp looks like this:
#include <iostream>
#include <string>
#include "Field.h"
#include "Method.h"
using namespace std;
void increaseAge(Object* obj){
age++;
}
int main(){
Method* m2 = new Method("increaseAge",increaseAge);
Object Daniel = new Male;
m2.invoke(Daniel);
}

C++ Deque Custom Class Templating

I have a class "board" that I am trying to put a deque member in. I wrote the code with an int object for the deque and everything worked fine, so I think it is a problem with setting the Template for the custom class, but I have never done this in C++.
board.h:
#ifndef __board_h__
#define __board_h__
using namespace std;
#include <deque>
#include "noble_card.h"
class board;
class board
{
public: deque<noble_card> line;
public: board();
public: ~board();
};
#endif
board.cpp:
#include <deque>
#include "noble_card.h"
board::board() {
deque<noble_card> line;
}
board::~board() {}
I think I may have a problem with the construction method here, as deque is erroring out on so many things I am having trouble tracking it down.
noble_card.h:
#include <string>
#ifndef __noble_card_h__
#define __noble_card_h__
#include "board.h"
class noble_card
{
public: string name;
public: int id;
public: int vp;
public: noble_card(int _vp);
public: ~noble_card();
};
#endif
noble_card.cpp:
#include "noble_card.h"
noble_card::noble_card(int _vp) {
this->vp = _vp;
}
noble_card::~noble_card() {
}
Now, the problem comes when I try to push elements onto this deque, i have a for loop like such:
board b;
for (unsigned i = 0; i < 12; i++) {
noble_card nc(i);
b->line.push_back( nc );
}
I keep getting assignment operator could not be generated, copy constructor could not be generated, and std::deque : 'noble_card' is not a valid template type argument for parameter '_Ty' (board.h). I am assuming this is because I haven't templated my classes and overridden the copy/constructor methods to tell the deque how to sort/remove/alloc/copy this type of class. I'm basically just trying to get a custom c++ class to be used in a deque and it is a lot more complicated than C# and other standard libraries I've used where you just push it on there and it takes care of it.
EDIT:
#ifndef __noble_card_h__
#define __noble_card_h__
using namespace std;
class noble_card {
public: char* name;
public: int id;
public: int vp;
public: noble_card(char* _name, int _id, int _vp) : name(_name), id(_id), vp(_vp) {}
};
#endif
Setting up noble_card.h this way seems to satisfy the requirements for the copy/alloc/constructor for deque. I still don't fully understand it as it seems to be shorthand, so if anyone could expand on line 10 I'd much appreciate it. For now This change has me moving forward.
Small fix of your immediate problem:
Your variable b is not a pointer and the operator->
b->line.push_back(nc);
will therefore not work. You have to use the operator.
b.line.push_back(nc);
C++ is not C# (mini code review)
You write that you are coming from C#. There are a lot of stylistic differences between the two languages that you should be aware off. I don't know C#, but here is a 2nd take on your code, taking care of the sorest points (I'm commenting out the header inclusions as it doesn't work on the online compiler I use)
// noble_card.h
#include <string>
class noble_card
{
public: // single section of public stuff (are you sure you don't need private data?)
std::string name; // never do: "using namespace std;" in a header!
int id;
int vp;
noble_card(int _vp);
// compiler-generated default constructor is just fine here
};
// noble_card.cpp
noble_card::noble_card(int _vp): vp(_vp) {} // initialize member in initializer-list
// board.h
// #include "noble_card.h"
#include <deque>
class board
{
public: // single section of public stuff (are you sure you don't need private data?)
std::deque<noble_card> line; // never do: "using namespace std;" in a header!
// compiler generated default constructor and destructor are just fine here
};
// board.cpp (not necessary for your current impl)
// #include "board.h" // takes care of "noble_card.h"
// main.cpp
int main()
{
board b;
for (unsigned i = 0; i < 12; ++i) {
b.line.emplace_back(i); // C++11 allows you to construct-in-place
}
}
Live Example.
You should Google this site to get in-depth explanations of the points that I write in the above code behind the // comments.