I write c++ with c++11 and have a question as title.
Ex.
class Hi {
public:
Hi(){};
test() {cout << "test" << endl;};
}
void noop(){
; // noop
};
int main(){
Hi hi();
hi.test = noop; // just example, not real case
return 0;
}
Is that possible to replace test() of class Hi to a noop function in runtime!? Thanks.
You can't replace any function at runtime, whether class member or not.
However, you can achieve the desired effect by using a variable.
(This is yet another example of the "add a level of indirection" method of solving problems.)
Example:
class Hi {
public:
Hi(): test([this]() { do_test(); }) {}
std::function<void()> test;
void do_test() { cout << "test" << endl; }
};
void noop(){}
int main(){
Hi hi;
hi.test(); // Outputs 'test'
hi.test = noop;
hi.test(); // Does nothing
}
You have to think object oriented. In this case you have to elevate your function to be an object we can name it MethodClass then your function in the class Hi will be a pointer to that class. Below a simple example
#include <memory>
class BaseMethodClass
{
public:
virtual void method() = 0;
};
class MethodClass1 : public BaseMethodClass
{
public:
virtual void method()
{
// your implementation here
}
};
class MethodClass2 : public BaseMethodClass
{
public:
virtual void method()
{
// your implementation here
}
};
class Hi
{
public:
Hi() { method = nullptr; };
void setMethod(BaseMethodClass* m) { method.reset(m); }
void test() { if (method) method->method(); };
private:
std::shared_ptr<BaseMethodClass> method;
};
int main()
{
Hi hi;
hi.setMethod(new MethodClass1());
hi.test();
hi.setMethod(new MethodClass2());
hi.test();
return 0;
}
This way you can override your methos as you want not just noop
Related
Given a class:
class myClass{
// ...
private:
int helperFuncForA();
int secondhelperFuncForA();
public:
void A();
// ...
};
Suppose that the helper functions are not used outside of A; how do I encapsulate them such that calling them outside of A is impossible? Do I do:
class myClass{
// ...
public:
class {
private:
int helperFuncForA();
int secondhelperFuncForA();
public:
void call();
} A;
// ...
};
and then call by writing:
myClass obj;
obj.A.call();
? Perhaps, I could overload A's () operator instead of making the call() function for convenience. What is the correct way?
The correct way is using of lambdas:
class myClass{
// ...
private:
// remove from here
//int helperFuncForA();
//int secondhelperFuncForA();
public:
void A();
// ...
};
// somewhere
void myClass::A()
{
auto helperFuncForA = [this]() -> int
{
//...
return 1;
};
auto secondhelperFuncForA = [this]() -> int
{
//...
return 2;
};
//...
int x = helperFuncForA();
x += secondhelperFuncForA();
}
If some method can only be used by in the function void A(), you probably need a class.
But you can do something like this if you want :
#include <iostream>
class ClassTest
{
public:
struct A{
private:
void helperFunc() {
std::cout << "Executing Helper Func " << std::endl;
}
public:
void operator() (){
helperFunc();
}
};
A a;
void classFunc(){
//a.helperFunc(); <- Impossible helperFunc private
a();
}
};
int main()
{
ClassTest c;
c.classFunc();// Print : Executing Helper Func
//OR
c.a();// Print e: Executing Helper Func
}
This question already has answers here:
How to store object of different class types into one container in modern c++?
(2 answers)
Closed 3 years ago.
I have multiple classes with same function as below
class A
{
void display()
{
// display something
}
};
class B
{
void display()
{
// display something two
}
};
I want to store difference class at a list or a vector and loop to call the same function with same name
int main()
{
A * a;
B * b;
//list or vector to store object
std::vector < Something that can store different class > listofclass;
listofclass.emplace_back(a);
listofclass.emplace_back(b);
for (int i = 0; i < listofclass.size(); i++)
{
listofclass[i].display();
}
}
Is that possible to do like this?
Because there is separate classes, having different purpose, and now i try to group them together
Or there is other alternative way to achieve something like this
If you control the definition of A and B, you can write a common base class, and have them inherit it.
class can_display {
public:
virtual void display() = 0;
virtual ~can_display() = default;
};
class A : public can_display
{
void display() override
{
// display something
}
};
class B : public can_display
{
void display() override
{
// display something two
}
};
int main()
{
A a;
B b;
std::vector<can_display *> displayables;
displayables.push_back(&a);
displayables.push_back(&b);
for (can_display * displayable : displayables)
{
displayable->display();
}
}
As an alternative to changing the definition of A and B to inherit from a common base, you can have a wrapper that inherits.
template <typename T>
class can_display_impl {
T * wrapped;
public:
can_display_impl(T * wrapped) : wrapped(wrapped) {}
void display() override { wrapped->display(); }
}
template <typename T>
std::unique_ptr<can_display> make_can_display(T & wrapped) {
return std::make_unique<can_display_impl<T>>(&wrapped);
}
int main()
{
A a;
B b;
std::vector<std::unique_ptr<can_display>> displayables;
displayables.emplace_back(make_can_display(a));
displayables.emplace_back(make_can_display(b));
for (auto & displayable : displayables)
{
displayable->display();
}
}
You have two solutions for this problem:
Use inheritance and just make a abstract class that will be a interface for your classes. In class A and class B just inherit from that interface and in std::vector hold pointer to base class.
#include <vector>
#include <iostream>
#include <memory>
class Interface_display {
public:
virtual void display() = 0;
virtual ~Interface_display(){};
};
class A : public Interface_display
{
public:
void display() override
{
std::cout << "Display from A\n";
}
~A() override = default;
};
class B : public Interface_display
{
public:
void display() override
{
std::cout << "Display from B\n";
}
~B() override = default;
};
int main(void)
{
std::vector<std::unique_ptr<Interface_display>> v;
v.emplace_back(std::make_unique<A>());
v.emplace_back(std::make_unique<B>());
for (const auto &element: v) {
element->display();
}
}
And if you are using c++17, you could use std::variant and wrap objects of your class to std::variant:
#include <vector>
#include <iostream>
#include <variant>
class A
{
public:
void display()
{
std::cout << "Display from A\n";
}
};
class B
{
public:
void display()
{
std::cout << "Display from B\n";
}
};
int main(void)
{
using variant_t = std::variant<A, B>;
std::vector<variant_t> v;
v.emplace_back(A());
v.emplace_back(B());
for (auto &element: v) {
std::visit([](auto &x) { x.display(); }, element);
}
}
https://wandbox.org/permlink/8VBmziWzafbPZk99
A way to solve this problem is by using polymorphism. You make a superclass, which contains a pure virtual version of this function and let both A and B inherit from this class. By doing this, you can dynamic_cast any pointer of type A or B to a superclass type, on which you have defined the display function.
This will get you something like this
class C {
public:
virtual void display() = 0;
virtual ~C() = default;
};
class A : public C {
public:
void display() override {
std::cout << "A" << std::endl;
};
~A() override = default;
};
class B : public C {
public:
void display(){
std::cout << "B" << std::endl;
};
~B() override = default;
};
So you can do:
C* c = new A();
// You can put the types of C* in the same list, and iterate over this list and do on each element
c->display();
delete c;
there is error here(but when i try to send non //class function its workin);
like when i try to add normal void zad1(){somethin...} its works but when i try to add function from class its not :?
//Class that send function//
class Lekcja1 : public ZadanieW {
private:
int numerZad;
public:
Lekcja1(int num) {
this->numerZad = num;
};
~Lekcja1() {};
void tab();
virtual void LekcjaChose();
};
/*void Zad12() {
cout << "dupa" << endl;
}*/
void Lekcja1::tab() {
cout << "dupa" << endl;
};
void Lekcja1::LekcjaChose() {
wyborZadania* obj = new wyborZadania(numerZad,tab);//there is a problem
delete obj;
}
//Class that takin function//
class ZadanieW {
public:
virtual void LekcjaChose() = 0;
};
class wyborZadania{
public:
int _chose;
public:
wyborZadania(int num,void (*tab)()) {
this->_chose = num;
switch (_chose)
{
case 1:
(*tab)();
break;
default:
break;
}
}
~wyborZadania() {}
};
tab is a method of Lekcja1, which is different from a regular function because it needs access to all the data members of Lekcja1.
You can either make Lekcja1::tab a static method, which hides access to data member and makes it a normal function:
class Lekcja1 : public ZadanieW {
//...
public:
static void tab();
//...
};
Or if you need tab to access data members of Lekcja1, then the wyborZadania constructor should take a pointer-to-member of Lekcja1 and an instance of Lekcja1, instead of a function pointer:
wyborZadania(int num,void (Lekcja1::*tab)(), Lekcja1& instance) {
// ...
(instance.*tab)();
// ...
}
If you need that to be more flexible or accept different kinds of classes, then wyborZadania should take an std::function, which is a rich wrapper around a function that will let you bind arguments and data.
wyborZadania(int num,std::function<void()> tab) {
// ...
tab();
// ...
}
And then in LekcjaChose() pass a lambda to call tab():
wyborZadania* obj = new wyborZadania(numerZad,[this](){ tab(); };
demo: https://godbolt.org/z/XfwpSJ
Pointer to member functions are passed differently. You need to pass it like this:
template<class T>
wyborZadania(int num,void (T::*&tab)()) {
this->_chose = num;
switch (_chose)
{
case 1:
(*tab)();
break;
default:
break;
}
}
For this to work Lekcja1::tab() should be declared static, otherwise you also have to pass an object, too. See the live example.
a non-static method cannot be sent as an argument without specifying the object of the class.
Below code uses std::function() to acheive this in simple code.
#include <iostream>
using namespace std;
#include <functional>
//class wyborZadania;
//Class that takin function//
class ZadanieW {
public:
virtual void LekcjaChose() = 0;
};
//Class that send function//
class Lekcja1 : public ZadanieW {
private:
int numerZad;
public:
Lekcja1(int num) {
this->numerZad = num;
};
~Lekcja1() {};
void tab();
virtual void LekcjaChose();
};
void Zad12() {
cout << "dupa" << endl;
}
class wyborZadania {
public:
int _chose;
private:
wyborZadania() {};
public:
wyborZadania(int num, std::function<void()> tab) {
this->_chose = num;
switch (_chose)
{
case 1:
tab();
break;
default:
break;
}
}
~wyborZadania() {}
};
void Lekcja1::tab() {
cout << "dupa1" << endl;
};
void Lekcja1::LekcjaChose() {
wyborZadania* obj = new wyborZadania(numerZad, std::bind(&Lekcja1::tab, this));//there is a problem
//wyborZadania* obj = new wyborZadania(numerZad, Zad12);//there is a problem
delete obj;
}
int main()
{
Lekcja1 obj(1);
obj.LekcjaChose();
}
I want an attribute in a C++ class be an uninstantiated class from a particular class heirachy. All members of this class heirachy would then implement the same method, meaning I could instantiate the object and then use the method when the situation calls for it. Here's some code (that doesn't compile) demonstrating what I mean:
#include <iostream>
using namespace std;
class Event {
public:
Event() = default;
virtual void go() = 0;
};
class EventA : Event {
public:
EventA() = default;
void go(){
cout << "Running event A"<< endl;
}
};
class EventB : Event {
public:
EventB() = default;
void go(){
cout << "Running event B"<< endl;
}
};
class Situation{
private:
Event* current_event = &EventA; //Problematic code: EventA does not refer to a value
public:
Situation() = default;
void setEvent(Event* event){
current_event = event;
}
void runEvent(){
current_event.go();
}
};
int main() {
Situation situation;
situation.runEvent();
situation.setEvent(&EventB);
situation.runEvent();
return 0;
};
No, you cannot form pointers to classes, and you cannot invoke [non-static] member functions without a class instance (object).
You should probably std::make_unique an instance of the type you want to use.
Don't forget to give your base a virtual destructor, since you're doing polymorphism things.
A static alternative would be std::variant.
In two places, you seem to be doing what could be described as trying to take a pointer from a type:
Event* current_event = &EventA;
and
situation.setEvent(&EventB);
This doesn't work and is not really a thing with proper meaning in C++. What you are trying to do could be implemented in 3 different ways I can think of.
Method 1: instead of having a class, you can have a function pointer, and pass the function pointer as parameter:
#include <iostream>
using namespace std;
void eventA_go(){
cout << "Running event A"<< endl;
}
void eventB_go(){
cout << "Running event B"<< endl;
}
class Situation{
private:
using EventFunctionPtr = void (*)();
EventFunctionPtr current_event = &eventA_go;
public:
Situation() = default;
void setEvent(EventFunctionPtr event){
current_event = event;
}
void runEvent(){
current_event();
}
};
int main() {
Situation situation;
situation.runEvent();
situation.setEvent(&eventB_go);
situation.runEvent();
return 0;
};
Method 2: you can make this code a little more generic, by allowing any type of callable in your Situation class, not only function pointers:
#include <iostream>
#include <functional>
using namespace std;
void eventA_go(){
cout << "Running event A"<< endl;
}
void eventB_go(){
cout << "Running event B"<< endl;
}
class Situation{
private:
std::function<void ()> current_event = eventA_go;
public:
Situation() = default;
template <typename F>
void setEvent(F&& event){
current_event = event;
}
void runEvent(){
current_event();
}
};
int main() {
Situation situation;
situation.runEvent();
situation.setEvent(&eventB_go);
situation.runEvent();
return 0;
};
Method 3: you can go back to your original idea of having a base class that must be implemented to provide a go() method, but in this case you will actually have to make sure the objects you are calling do exists. A possible way to do it is with std::unique_ptr:
#include <iostream>
#include <memory>
using namespace std;
class Event {
public:
Event() = default;
virtual ~Event() = default;
virtual void go() = 0;
};
class EventA : public Event {
public:
EventA() = default;
void go(){
cout << "Running event A"<< endl;
}
};
class EventB : public Event {
public:
EventB() = default;
void go(){
cout << "Running event B"<< endl;
}
};
class Situation{
private:
std::unique_ptr<Event> current_event = std::make_unique<EventA>();
public:
Situation() = default;
void setEvent(std::unique_ptr<Event>&& event){
current_event = std::move(event);
}
void runEvent(){
current_event->go();
}
};
int main() {
Situation situation;
situation.runEvent();
situation.setEvent(std::make_unique<EventB>());
situation.runEvent();
return 0;
};
Notice that, in this case, the destructor of the abstract class must be virtual, and the inheritance must be public.
You seem to be confused about classes and variables. Which object would situation.runEvent(); run on? I think you want to publicly derive the classes from Event and initialize current_event when you need to. You don't need to do anything like current_event = &EventB. C++ automagically determines which function is needed to be called based on what current_event is dynamically pointing to. Here's what I think you meant to do:
#include <cassert>
#include <iostream>
class Event {
public:
virtual void go() = 0;
virtual ~Event() = default; // Don't forget the virtual destructor
};
class EventA : public Event {
public:
void go() override { std::cout << "Running event A" << std::endl; }
};
class EventB : public Event {
public:
void go() override { std::cout << "Running event B" << std::endl; }
};
class Situation {
private:
Event* current_event = nullptr;
public:
void setEvent(Event* event) { current_event = event; }
void runEvent() {
assert(current_event);
current_event->go();
}
};
int main() {
Situation situation;
EventA a;
EventB b;
situation.setEvent(&a);
situation.runEvent();
situation.setEvent(&b);
situation.runEvent();
}
I have a problem which I encounter again and again in a similar way.
For example:
I have an abstract base class which acts as interface for a series of concrete classes which act as, let's say, data containers.
class DataInterface
{
public:
DataInterface();
~DataInterface();
virtual void FetchData(void) = 0;
virtual void ProcessData(void) = 0;
virtual void ClearData(void) = 0;
}
The concrete classes would look like this:
class BinaryData: public DataInterface
{
public:
BinaryData();
~ BinaryData();
virtual void FetchData(void);
virtual void ProcessData(void);
virtual void ClearData(void);
private:
bool m_boolData;
}
class IntegerData: public DataInterface
{
public:
IntegerData();
~ IntegerData();
virtual void FetchData(void);
virtual void ProcessData(void);
virtual void ClearData(void);
private:
int m_intData;
}
The subclasses implement the interface which they inherited from DataInterface. But they have different attributes to hold their data. So far so good.
I can use the classes in the main function like that:
int main()
{
int IntegerData;
bool BoolData;
DataInterface *pData1 = new BinaryData();
DataInterface *pData2 = new IntegerData();
pData1->FetchData();
pData2->FetchData();
pData1->ProcessData();
pData2->ProcessData();
// now I want to get the data of pData1 and pData2, for example to write it into a file, show in visualization, ...
IntegerData = pData2->GetData() ????
BoolData = pData1->GetData() ????
}
Now comes the problem:
How do I get the data from the concrete classes? I have only base class pointers, so I would need to define an abstract getter method in DataInterface. But the signature of the getter method wouold vary from subclass to subclass. For example one time I need to return an integer, one time I need to return a bool type.
Please give me a hint, this problem drives me nuts :/
Make a non-virtual GetData() member on each derived class. Then, if you know for certain the actual class of your objects, you can simply perform a static cast and call GetData():
int intData = static_cast<IntegerData*>(pData2)->GetData();
If you don't know the class, then you need to perform a dynamic cast and check its result:
if (IntegerData* _pData2 = dynamic_cast<IntegerData*>(pData2))
{
int intData = _pData2->GetData();
// Do stuff with the int
}
else if (BinaryData* _pData2 = dynamic_cast<BinaryData*>(pData2))
{
bool binaryData = _pData2->GetData();
// Do stuff with the bool
}
If you want to pass your data to another entity, you need an abstraction of it.
There are 2 common ways to achieve this:
1:
Use void*.
class DataInterface
{
public:
...
virtual void* GetData() = 0;
};
class BinaryData: public DataInterface
{
public:
virtual void* GetData() { return &m_boolData; }
private:
bool m_boolData;
};
In main use it like this:
int main()
{
bool BoolData;
DataInterface *pData1 = new BinaryData();
pData1->FetchData();
pData1->ProcessData();
BoolData = *(bool*))pData1->GetData());
}
Advantage of this approach is in its simplicity.
Disadvantages are direct access to internal of an object (breaking encapsulation) and also misuse of polymorphism (why do you need an interface if you eventually cast to a type related to a concrete derivative?)
2:
A more robust way is to not send the raw data to a client from out of your concrete object but to make a communication with clients an additional role of the object.
class DataInterface
{
public:
...
virtual void SendData() = 0;
};
class BinaryData: public DataInterface
{
public:
...
virtual void SendData()
{
//do your stuff here, you know the exact type of your data
}
};
int main()
{
bool BoolData;
DataInterface *pData1 = new BinaryData();
pData1->FetchData();
pData1->ProcessData();
pData1->SendData();
}
Note, this is a very stripped example but it demonstrates the idea. Normally, in a real use case you would register clients with you class and send the data to them via a defined interface.
I am not really sure this is a "good" practice but here is one way to solve this.
One advantage with this is that if you try to get the wrong type of data you can get custom error messages. And you can avoid casts (I am not a fan of them).
class DataInterface
{
public:
DataInterface();
~DataInterface();
virtual void FetchData(void) = 0;
virtual void ProcessData(void) = 0;
virtual void ClearData(void) = 0;
virtual int getIntData() { // Error message }
virtual bool getBoolData() { // Error message }
};
class BinaryData: public DataInterface
{
public:
BinaryData();
~ BinaryData();
virtual void FetchData(void);
virtual void ProcessData(void);
virtual void ClearData(void);
virtual int getIntData() { // Error message }
virtual bool getBoolData() { return m_boolData; }
private:
bool m_boolData;
}
class IntegerData: public DataInterface
{
public:
IntegerData();
~ IntegerData();
virtual void FetchData(void);
virtual void ProcessData(void);
virtual void ClearData(void);
virtual int getIntData() { return m_intData; }
virtual bool getBoolData() { // Error message }
private:
int m_intData;
}
int main()
{
int IntegerData;
bool BoolData;
DataInterface *pData1 = new BinaryData();
DataInterface *pData2 = new IntegerData();
pData1->FetchData();
pData2->FetchData();
pData1->ProcessData();
pData2->ProcessData();
// now I want to get the data of pData1 and pData2, for example to write it into a file, show in visualization, ...
IntegerData = pData2->GetIntData();
BoolData = pData1->GetBoolData();
BoolData = pData2->GetBoolData() // This will tell you that you are trying to get bool from int class.
}
Here is one way of handling it with templates.
using namespace std;
template<typename T>
class DataInterface
{
public:
DataInterface(T d) : data(d) {}
virtual T GetData() = 0;
protected:
T data;
};
class BinaryData : public DataInterface<bool>
{
public:
BinaryData(bool b) : DataInterface<bool>(b) {}
virtual bool GetData() {return data;}
};
class IntegerData: public DataInterface<int>
{
public:
IntegerData(int i) : DataInterface<int>(i) {}
virtual int GetData() {return data;}
};
int main()
{
int myint;
bool mybool;
DataInterface<bool> *pData1 = new BinaryData(true);
DataInterface<int> *pData2 = new IntegerData(1);
// now I want to get the data of pData1 and pData2, for example to write it into a file, show in visualization, ...
myint = pData2->GetData();
mybool = pData1->GetData();
cout<<myint<<" "<<mybool<<endl;
}
A very simple way of achieving this is to design your base class so that it returns a variant type. A variant is a discriminated union container, which holds an object from an heterogeneous set of types (see http://www.boost.org/doc/libs/1_59_0/doc/html/variant.html). Here is a complete example:
#include <iostream>
#include <algorithm>
#include <boost/variant.hpp>
#include <memory>
using namespace std;
class DataInterface
{
public:
DataInterface(){};
virtual ~DataInterface(){};
virtual void FetchData(void) = 0;
virtual void ProcessData(void) = 0;
virtual void ClearData(void) = 0;
virtual boost::variant<bool,int,double,std::string> GetData()=0;
};
class IntResult : public DataInterface{
public:
IntResult() : resultInt(0){};
~IntResult(){};
virtual void FetchData() override {resultInt = 10;};
virtual void ProcessData() override {resultInt *= 10;}
virtual void ClearData() override {resultInt = 0;};
virtual boost::variant<bool,int,double,std::string> GetData()override{
return resultInt;
};
private:
int resultInt;
};
class StringResult : public DataInterface{
public:
StringResult() : resultString(""){};
~StringResult(){};
virtual void FetchData() {
resultString= "Hello World";
}
virtual void ProcessData() override {
std::transform(resultString.begin(), resultString.end(),resultString.begin(), ::toupper);
}
virtual void ClearData() override {resultString = "";}
virtual boost::variant<bool,int,double,std::string> GetData() override {
return resultString;
};
private:
std::string resultString;
};
int main() {
DataInterface* data;
IntResult* intResult = new IntResult;
StringResult* stringResult = new StringResult;
data = intResult;
data->FetchData();
data->ProcessData();
switch(data->GetData().which()){
case 0:
std::cout << "found bool: " << boost::get<bool>(data->GetData()) << std::endl;
break;
case 1:
std::cout << "found int: " << boost::get<int>(data->GetData()) << std::endl;
break;
case 2:
std::cout << "found double: " << boost::get<double>(data->GetData()) << std::endl;
break;
case 3:
std::cout << "found string: " << boost::get<std::string>(data->GetData()) << std::endl;
break;
default:
break;
}
data = stringResult;
data->FetchData();
data->ProcessData();
switch(data->GetData().which()){
case 0:
std::cout << "found bool: " << boost::get<bool>(data->GetData()) << std::endl;
break;
case 1:
std::cout << "found int: " << boost::get<int>(data->GetData()) << std::endl;
break;
case 2:
std::cout << "found double: " << boost::get<double>(data->GetData()) << std::endl;
break;
case 3:
std::cout << "found string: " << boost::get<std::string>(data->GetData()) << std::endl;
break;
default:
break;
}
delete intResult;
delete stringResult;
return 0;
}
Note that in your case a bool is implicitly convertible to an int so you could simply return ints all the time. The variant approach would work if you need to return truly heterogeneous types. Equivalently you could return a boost any, which can also lets you manipulate a heterogeneous union of types uniformly (see http://www.boost.org/doc/libs/1_59_0/doc/html/any.html). Finally if you don't want any dependencies on boost, it is not terribly difficult to roll out your own variant type, which can hold discriminate set of types.