Below is a simple strategy pattern implemented using the base class references to a derived object. The solution does not produce an expected result (12 and 2). When base class reference is switched to pointers, it works. Can someone explain what is happening behind the scenes with references here? The issue is in the setStrategy() method of the Context class. I am wondering why doesn't the strategy variable reference the ConcreteStrategy2 after the call to setStrategy() method?
#include <iostream>
class Strategy {
public:
virtual ~Strategy() = default;
virtual int execute(int x, int y) const = 0;
};
class ConcreteStrategy1 : public Strategy {
public:
int execute(int x, int y) const override
{
return x + y;
}
};
class ConcreteStrategy2 : public Strategy {
public:
int execute(int x, int y) const override
{
return x - y;
}
};
class Context {
Strategy &strategy;
public:
Context(Strategy &strategy) : strategy {strategy}
{
}
void setStrategy(Strategy &strat)
{
this->strategy = strat;
}
void doLogic() const
{
std::cout << strategy.execute(7, 5) << std::endl;
}
};
int main()
{
ConcreteStrategy1 strat;
Context context {strat};
context.doLogic();
ConcreteStrategy2 strat2;
context.setStrategy(strat2);
context.doLogic();
return 0;
}
You are trying to reassign a reference, but references cannot be reassigned. It assigns to Strategy object being referred to instead. If you make Strategy non-copyable/assignable that re-assignment through reference will fail to compile.
Use a pointer instead:
class Context {
Strategy* strategy;
public:
Context(Strategy &strategy) : strategy {&strategy} {}
void setStrategy(Strategy &strat) { this->strategy = &strat; }
void doLogic() const { std::cout << strategy->execute(7, 5) << std::endl; }
};
Using reference members is almost always a mistake because it breaks value semantics, as you observe. One can get away with using reference members in non-copyable classes.
Additional solution to Maxim Egorushkins answer.
You could also use std::reference_wrapper instead of a pointer:
class Context {
std::reference_wrapper<Strategy> strategy;
public:
Context(Strategy &strategy) : strategy {strategy} { }
void setStrategy(Strategy &strat) { this->strategy = strat; }
void doLogic() const { std::cout << strategy.get().execute(7, 5) << std::endl; }
};
Here are both versions next to each other:
https://gcc.godbolt.org/z/dveK9T
Related
I am using C++ 14 with clang on MacOS Sierra. I want to enforce a rule by design. Following is the rule.
I have a member variable in my class say:
unsigned int m_important_num;
There are 4 methods in my class.
fun1();
fun2();
fun3();
fun4();
Objective:
I want only fun2() to be able to change the value of m_important_num.
Question:
Is it possible to make it compiler error if any method other than fun2() changes the variable?
One possible way is to declare it const somehow empower fun2() to change const variables? Is this a good solution? Or are their any better solutions?
Secondary question:
Is it a wrong design to try do such a thing?
Sort of, with additional layer:
class S1 {
public:
void fun2() { /*Modify m_important_num */ }
unsigned int getImportantNum() const { return m_important_num;}
private:
unsigned int m_important_num;
};
class S2 : private S1
{
public:
void fun1();
using S1::fun2; // or void fun2() {S1::fun2();}
void fun3();
void fun4();
};
As Yakk commented, if func2 need access to S2 members, CRTP can solve that:
template <typename Derived>
class S1 {
public:
void fun2() { asDerived().foo3(); /*Modify m_important_num */ }
unsigned int getImportantNum() const { return m_important_num;}
private:
Derived& asDerived() { return stataic_cast<Derived&>(*this); }
private:
unsigned int m_important_num;
};
class S2 : private S1<S2>
{
// friend class S1<S2>; // If required.
public:
void fun1();
using S1::fun2; // or void fun2() {S1::fun2();}
void fun3();
void fun4();
};
Encapsulate it down. Put m_important_num in its own class. Aggregate it in your existing class. Have a getter for it. Then put fun2() as a member function of your inner class.
I little variant (if I understand correctly) of the Jeffrey solution: put the variable in an inner class and make it private; create a public getter and make func2() friend to the inner class.
I mean
struct foo
{
int f1 () { return b0.getVal(); }; // you can read `val` everywhere
void f2 () { b0.val = 42; }; // you can write `val` in f2()
void f3 () { /* b0.val = 42; ERROR ! */ }; // but only in f2()
class bar
{
private:
int val = 24;
public:
int getVal () { return val; }
friend void foo::f2 ();
};
bar b0;
};
In other words: friend is your friend.
If you want to prevent a method from modifying any member in the class you can use the trailing const identifier:
class something{
private:
unsigned int var;
public:
void fun1() const;
void fun2();
void fun3() const;
void fun4() const;
}
Here, only fun2() will be able to modify the variable.
I know there are lots of good answers, but there is also an option that you sort of alluded to in your question:
One possible way is to declare it const somehow empower fun2() to change const variables?
#include <iostream>
using uint = unsigned int;
class Test
{
const uint num;
public:
Test(uint _num)
:
num(_num)
{}
uint get_num() const
{
return num;
}
void can_change_num(uint _new_num)
{
uint& n(const_cast<uint&>(num));
n = _new_num;
}
void cant_change_num(uint _new_num)
{
// num = _new_num; // Doesn't compile
}
};
int main()
{
Test t(1);
std::cout << "Num is " << t.get_num() << "\n";
t.can_change_num(10);
std::cout << "Num is " << t.get_num() << "\n";
return 0;
}
Produces
Num is 1
Num is 10
You already got lots of good answers to your primary question. I'll try to address the secondary one.
Is it a wrong design to try do such a thing?
It's hard to say w/o knowing more about your design. In general anything like this detected during a code review would raise a big red flag. Such a protection makes sense in a case of a big class with convoluted logic/implementation. Otherwise why would you like to go an extra mile and make your code much more complicated? The fact you seek for this can indicate your class became unmanageable.
I'd recommend to consider splitting it to smaller parts with better defined logic where you won't worry such mistakes can happen easily.
I am trying to study static polymophism and I implemented the following code. Thanks to the comments from StackOverflow members, I came to understand that what I just wrote is not static polymophism, but actually template-based policy-pattern.
Can anyone give any insight about how to turn this piece of code into static polymophism?
#include <iostream>
template<typename T>
class Interface {
T ex;
public:
double getData() {
return ex.getData(0);
}
};
class Extractor1 {
public:
double getData(const int a) {
return 1;
}
};
class Extractor2 {
public:
double getData(const int a) {
return 2;
}
};
int main() {
// here is the problem: the following 2 variables belong to different types. Therefore, I cannot create an array of pointers which point to the base class
Interface<Extractor1> e1;
Interface<Extractor2> e2;
std::cout<<"FE1 "<< e1.getData() <<" FE2 "<< e2.getData()<<std::endl;
return 0;
}
You can change your code like this to achieve static polymorphism:
#include <iostream>
template <typename T>
class Interface {
public:
double getData(int a) {
return static_cast<T *>(this)->getData(a);
}
};
class Extractor1 : public Interface<Extractor1> {
public:
double getData(int a) {
return 1;
}
};
class Extractor2 : public Interface<Extractor2> {
public:
double getData(int a) {
return 2;
}
};
int main() {
Interface<Extractor1> e1;
Interface<Extractor2> e2;
std::cout << e1.getData(1) << " " << e2.getData(2) << std::endl;
}
The advantage of using static polymorphism is you avoid paying the runtime cost of a vtable lookup like you would when using virtual functions. The drawback though, as I see you are running into based on your 'array' comment, is that you cannot place these different Extractor classes into an array or any other container, because they are both inheriting different base types. The only way around this, aside from using something like a tuple or a container filled with boost::any types, is creating a common base class for your Extractor classes.
I've been banging my head for quite some time now trying to create an array/vector that can contain references to several types of variables, see the example:
class Validate
{
private:
some_array/vector[]; //0 would refer to x, 1 to y, and so on..
uint8_t x;
uint16_t y;
int32_t z;
public:
Validate();
void doSomething(uint8_t &member);
void doSomething(uint16_t &member);
void doSomething(int32_t &member);
}
The whole point is so that I can use this array/vector easily in a "for loop", something like this:
void Validate::doSomething(uint_8 &member)
{
//Do whatever with the variable refered to.
}
Validate::Validate()
{
for(int i = 0 ; i < 2 ; i++)
doSomething(some_array/vector[i]);
}
Perhaps somebody have an answer or possibly a better solution for me.
You have two problems. Firstly, a container cannot contain elements of different types. Secondly, you cannot store references in a container.
One way of solving the first problem is to use std::variant from C++17 (or boost::variant). To solve the second problem you could use std::reference_wrapper:
class Validate {
using Uint8Ref = std::reference_wrapper<uint8_t>;
using Uint16Ref = std::reference_wrapper<uint16_t>;
using Uint32Ref = std::reference_wrapper<int32_t>;
using MemberType = std::variant<Uint8Ref, Uint16Ref, Uint32Ref>;
std::vector<MemberType> members;
uint8_t x;
uint16_t y;
int32_t z;
public:
Validate();
void doSomething(uint8_t &member);
void doSomething(uint16_t &member);
void doSomething(int32_t &member);
};
Validate::Validate() : members({std::ref(x), std::ref(y), std::ref(z)}) {
for (auto member : members) {
std::visit([this](auto member){this->doSomething(member);}, member);
}
}
Live demo.
Alternatively, you could create a polymophic base class for a member that you can store in a container:
class MemberType {
public:
virtual ~MemberType(){}
virtual void accept(Validate& validate) = 0;
};
class Validate {
std::array<std::unique_ptr<MemberType>, 3> members;
// as before...
};
template<typename T>
class MemberTypeImpl : public MemberType {
T& member;
public:
MemberTypeImpl(T& member) : member(member){}
void accept(Validate& validate) override {
validate.doSomething(member);
}
};
template<typename T>
std::unique_ptr<MemberType> make_member_type(T& member) {
return std::make_unique<MemberTypeImpl<T>>(member);
}
Validate::Validate()
: members({make_member_type(x), make_member_type(y), make_member_type(z)}) {
for (auto& member : members) {
member->accept(*this);
}
}
I have a set of multiple C++ classes that have the same interface (not derived from each other though). I'm trying to wrap these to make them available in .NET.
I currently have a method that defines the wrapper class using C/C++ #defines and then I can subsequently instantiate classes with a simple line of code
However I can't debug this. Ideally I would like to be able to use a generic or a template. However I can't use a C++ type inside a generic which would be the ultimate way to solve this problem.
Has anyone any idea of how I can do this without using the dreaded macros?
EDIT:
OK Here is an example of the templated class I have written:
template< typename CPPResamplerClass >
ref class TResampler
{
CPPResamplerClass* pResampler;
public:
TResampler( int inputSampleRate, int outputSampleRate, int bufferLen ) :
pResampler( new CPPResamplerClass( inputSampleRate, outputSampleRate, bufferLen ) )
{
}
~TResampler()
{
this->!ResamplerName();
}
!TResampler()
{
if (pResampler)
{
delete pResampler;
pResampler = nullptr;
}
}
property int HistorySize
{
int get()
{
return pResampler->HistorySize();
}
}
array< float >^ ResampleAudio(array< float >^ in)
{
pResampler->Get
array< float >^ out = gcnew array< float >(in->Length);
cli::pin_ptr< float > pIn = &in[0];
cli::pin_ptr< float > pOut = &out[0];
unsigned int inLen = in->Length;
unsigned int outLen = out->Length;
if (pResampler->ResampleAudio(pOut, outLen, pIn, inLen))
{
System::Array::Resize(out, outLen);
return out;
}
return nullptr;
}
};
typedef TResampler< ::Vec::SpeexResample > SpeexResample;
I then want to access this from C# however SpeexResample does not exist. This could well be because I am using a typedef ...
Templates don't exist until they're instantiated. While you could instantiate one explicitly:
template ref class TResampler<SomeNativeClass>;
It wouldn't be exactly user-friendly to use from C#. The exported type will literally have angle brackets in its name. Good luck using that. In C# it's only doable through reflection.
The next best thing is to use derived types. Here's a minimal example:
#include "stdafx.h"
#include <iostream>
namespace CppCli {
class NativeClassA
{
int foo;
public:
NativeClassA(int foo) : foo(foo) { std::cout << "Built native class A" << std::endl; }
int getFoo() const { return foo; }
};
class NativeClassB
{
int foo;
public:
NativeClassB(int foo) : foo(foo) { std::cout << "Built native class B" << std::endl; }
int getFoo() const { return foo; }
};
template<typename NativeClass>
public ref class ManagedWrapper
{
NativeClass* ptr;
public:
ManagedWrapper(int foo)
: ptr(new NativeClass(foo))
{}
~ManagedWrapper()
{
this->!ManagedWrapper();
}
!ManagedWrapper()
{
if (ptr)
{
delete ptr;
ptr = nullptr;
}
}
property int Foo { int get() { return ptr->getFoo(); } }
};
public ref class ManagedWrapperA : ManagedWrapper<NativeClassA>
{
public:
ManagedWrapperA(int foo) : ManagedWrapper(foo) {}
};
public ref class ManagedWrapperB : ManagedWrapper<NativeClassB>
{
public:
ManagedWrapperB(int foo) : ManagedWrapper(foo) {}
};
};
Sure enough, ManagedWrapperA and ManagedWrapperB are visible from C#. Maybe you could macro these definitions and still get a decent debugging experience.
I need some help on a strange mix between function pointers and templates...
My target :
You have a class : template<typename B> class A, and A instanciate a B member. Now I want to acces B getter/setter.
I tried this :
class B_example
{
public:
B_example(int v):m_var(v){}
int getVar() { return m_var; }
void setVar(int v) { m_var = v; }
private:
int m_var;
};
template<typename B> class A
{
public:
A():m_b(B(5))
{
get = &m_b.getVar;
set = &m_b.setVar;
}
int (B::*get)();
void (B::*set)(int);
private:
B m_b;
};
int main(int argc, char** argv)
{
A<B_example> A_instance;
B_example B_instance(5);
int a = (A_instance.get*)();
std::cout << a << std::endl;
}
Thank's for any help.
Alexandre
First, fix the syntax errors:
get = &B::getVar;
set = &B::setVar;
Then, the member-function pointer needs to be called on an object. Without knowing the purpose of these strange pointers, I can't guess what you want to do here. Maybe you want to call on B_instance:
int a = (B_instance.*A_instance.get)();
Or maybe you want to call it on the m_b object within A_instance; but you can't do that because it's private. If that's the case, you probably just want regular member functions, rather than weird function pointers
int get() {return m_b.getVar();}
void set(int v) {m_b.setVar(v);}
These:
get = &m_b.getVar;
set = &m_b.setVar;
Should be:
get = &B::getVar;
set = &B::setVar;
And (A_instance.get*)() should be (B_instance.*A_instance.get)().