I'm working on some code, which has a model similar to the following (it is a small part of a much larger application). In short, one of the classes (Class B) registers itself with another class (Class A) by passing this. Class B gets destroyed at some point in the larger application. Class A has a method invoked which depends on B and B is invoked after being destroyed (after doing a nullptr check). Rewriting this application to not have this pattern is not really an option. In A::GetVal() how do I correctly determine if B has already been destroyed? I can change the method signature for RegisterB(), but ultimately B needs to register itself with A and B can be destroyed at any time.
Classes.h:
#ifndef CLASSES_H
#define CLASSES_H
#pragma once
#include <iostream>
class B;
class A
{
private:
B* m_b;
int m_val;
public:
A(int val) : m_val(val) {}
int GetVal();
void RegisterB(B* b) { m_b = b; }
};
class B
{
private:
int m_val;
public:
B(int val) : m_val(val) {}
int GetVal() { return m_val; }
void RegisterWithA(A* a) { a->RegisterB(this); }
};
#endif
Classes.cpp:
#include "stdafx.h"
#include "Classes.h"
int A::GetVal()
{
if (m_b != nullptr)
{
m_b->GetVal(); // How do I prevent this branch from getting called?
}
else
{
return -1;
}
}
And main:
#include "stdafx.h"
#include "Classes.h"
int _tmain(int argc, _TCHAR* argv[])
{
A* a = new A(-1);
B* b = new B(1);
b->RegisterWithA(a);
delete b;
int result = a->GetVal();
delete a;
return 0;
}
You can use std::shared_ptr<> in conjunction with std::weak_ptr<> to handle this.
#include <iostream>
#include <memory>
using namespace std;
class B;
class A
{
private:
std::weak_ptr<B> m_b;
int m_val;
public:
A(int val) : m_val(val) {}
int GetVal();
void RegisterB(std::shared_ptr<B> b) { m_b = b; }
};
class B : public std::enable_shared_from_this<B>
{
private:
int m_val;
public:
B(int val) : m_val(val) {}
int GetVal() { return m_val; }
void RegisterWithA(A* a) { a->RegisterB(shared_from_this()); }
};
int A::GetVal()
{
if(auto b = m_b.lock())
{
m_val = b->GetVal();
}
return m_val;
}
int main()
{
auto a = std::make_shared<A>(-1);
auto b = std::make_shared<B>(1);
b->RegisterWithA(a.get());
b.reset();
int result = a->GetVal();
std::cout << result << '\n';
return 0;
}
You should rethink your design. Why are you using heap allocation of objects when it would be perfectly acceptable in this situation to have them on stack? Why are you not using inheritance and having B inherit from A? This whole quandry goes away when you don't force yourself to do unnecessary things.
If, for some reason you're forced to have have disparate heap-based objects then do something like wrap the allocated instance into a unique_ptr<> and pass the instance around or alternatively, as stated in Chad's answer, wrap it into a shared_ptr<> and maintain a weak_ptr<> reference for usage.
Unless the use of weak_ptr can be proven to be minimal and local to classes A and B (in that case it will be surely the recommended modification), it seems to me that a localized and minimal modification could be:
add to class A some unregisterB method (sets m_b to null)
maintain in B a set of A pointers. One sole pointer will do if the association is not many-to-one, that is, if an instance of B cannot be registered within many instances of A.
In B::~B, call unregisterB on all the A's in the set.
in B::RegisterWithA, add that instance (pointer) of A to the list.
The advantage here is that no other modifications are required in the application, only in the classes A and B.
Related
Im writing embedded code that cannot use memory allocation!
Also, static objects (therefore constructed before the microcontroller has executed the main funtion with all its initialization) shall be constructed within the main after the initialization, not before.
The only solution people suggest is to use static object pointers and allocate (construct them with new) during initialization. since this is no option for me, is there no other solution?
what i wanna do is as follows:
class A
{
public:
A(int a, bool b)
: myVal1(a), myVal2(b)
{
}
private:
int myVal1;
bool myVal2;
}
class B
{
public:
B(char x)
: myChar1(x) // <-- NO CONSTRUCTION, NO PARAMETER OF MYOBJECTA
{
}
void init()
{
// now i wanna construct myObjectA
myObjectA(123, false);
}
private:
char myChar1;
A myObjectA; // <-- NO CONSTRUCTION, NO PARAMETER
}
static B myObjectB('F'); // <-- NO CONSTRUCTION, NO PARAMETER OF MYOBJECTA
void global_init()
{
// ... do before construction
// now i wanna construct myObjectA
myObjectB.init();
//... do after construction
}
You can use a storage area large enough to create there an instance of A and placement new to control the time you create it.
As an example:
#include
#include
struct A {
A(int a, bool b): myVal1(a), myVal2(b) {}
void foo() {}
private:
int myVal1;
bool myVal2;
};
struct B {
B(char x): myChar1(x) {}
~B() { if(ptr) { ptr->~A(); } }
void init() {
ptr = new (&storage) A{123, false};
}
A * myObjectA() {
return ptr;
}
private:
char myChar1;
std::aligned_storage_t<sizeof(A), alignof(A)> storage;
A *ptr{nullptr};
};
static B myObjectB('F');
void global_init() {
// ... do before construction
// now i wanna construct myObjectA
myObjectB.init();
//... do after construction
}
int main() {
global_init();
myObjectB.myObjectA()->foo();
}
This won't allocate memory (if I got right what you mean for that) and the instance of A is actually created within B::init (that seems to be a requirement from what you wrote in your question).
If you have access to a compiler that supports C++17 or you can use the C++ Boost Libraries, std::optional is a valid alternative as suggested in another answer. Anyway you didn't specify the revision of the standard to which to adhere, so... Here is a way to go in any case.
Do you have boost available?
#include <boost/optional.hpp>
class A
{
public:
A(int a, bool b)
: myVal1(a), myVal2(b)
{
}
private:
int myVal1;
bool myVal2;
};
class B
{
public:
B(char x)
: myChar1(x) // <-- NO CONSTRUCTION, NO PARAMETER OF MYOBJECTA
{
}
A& getA() {
assert(myObjectA);
return myObjectA.get();
}
void init()
{
// now i wanna construct myObjectA
myObjectA.emplace(123, false);
}
private:
char myChar1;
boost::optional<A> myObjectA; // <-- NO CONSTRUCTION, NO PARAMETER
};
static B myObjectB('F'); // <-- NO CONSTRUCTION, NO PARAMETER OF MYOBJECTA
void global_init()
{
// ... do before construction
// now i wanna construct myObjectA
myObjectB.init();
//... do after construction
}
int main()
{
global_init();
}
I try to write an internal class that inherits from the real class for testing. The internal class copies temporary variables pass between classes.
Example:
#include <iostream>
#include <random>
class Internal_a;
class A {
public:
A() {}
const int test() const { return std::rand() % 10; }
private:
friend class Internal_a;
};
class Internal_a : public A {
public:
int test() {
_val = A::test();
return _val;
}
int _val;
};
class C {
public:
C(const A& a) { _x = a.test() * 2; }
private:
int _x;
};
int main() {
Internal_a i_a;
C c(i_a);
std::cout << i_a._val << "\n";
}
Problem:
The i_a._val value is not a copy of the result of A::test() during the construction of the c object. This is because inheritance doesn't work that way (ok, I just learned that.)
How to write a test that checks that temporary value (A::test()) ?
Is it possible to pass this by default ?
Here is what I currently have
class A
{
public:
template<typename T>
void dowithT(T t) {}
};
class B
{
public:
A a;
B()
{
//Calling 'dowithT' with 'this'
a.dowithT(this);
}
};
This function requires passing this from the caller of the function every time. So I wondered if there is a way to encapsulate this task, so that you don't need to pass this to dowithT.
I tried to do something like this:
class A
{
public:
// '= this' doesn't compile
template<typename T>
void dowithT(T t = this) {}
};
class B
{
public:
A a;
B()
{
//Calling 'dowithT' without 'this'
a.dowithT();
}
};
Unfortunately, I can't use templates, so my first solution isn't an option.
Is this possible?
Edit: I gave a concrete answer with my own implementation below. Also with a few mor deatils of what I wanted in the end.
TL;DR No, this is not possible.
this is not the same type in every class, you can't generalize it, so no, not possible.
Additionally, what would this be if doWithT() was called from a non-member function? nullptr?
That's why it isn't possible. You have to use a template.
Instead of B having a member of type A, it can inherit from A, and use something like the "curiously recurring template pattern."
If you cannot make class A a template, you can still do it like so:
class A
{
protected:
template <class T>
void dowithT()
{
T* callerthis = static_cast<T*>(this);
// callerthis is the "this" pointer for the inheriting object
cout << "Foo";
}
};
class B : public A
{
public:
B()
{
dowithT<B>();
// Or A::dowithT<B>();
}
};
dowithT() must only be called by an inheriting class (hence I made it protected), with the template parameter the caller's own type, or you'll break everything.
You may achieve exactly what you want by using a private mixin class to provide the dowithT method that takes no arguments:
#include <iostream>
#include <typeinfo>
class A
{
public:
template<typename T>
void dowithT(T* t) {
std::cout << "Hello, World" << typeid(*t).name() << std::endl;
}
};
template<class Owner>
struct calls_a
{
void dowithT()
{
auto p = static_cast<Owner*>(this);
p->a.dowithT(p);
}
};
class B
: private calls_a<B>
{
friend calls_a<B>;
A a;
public:
B()
{
//Calling 'dowithT' with 'this'
dowithT();
}
};
int main()
{
B b;
}
No, it is not possible. There is nothing really special about this when used as an argument to a function taking T* (template or not), it's just a pointer like any other.
this A is different from this B. In your first code, this refers to the caller, while in the second this refers to the callee. Thus what you want to do isnt really possible.
Here's one possibility, which might, or might not suit your needs:
template<typename T>
class A
{
public:
A(T t) : t(t) {}
void dowithT()
{
cout << "Foo";
}
private:
T t;
};
class B
{
public:
A<B*> a;
B() : a(this)
{
a.dowithT();
}
};
You could use a private method in class B that acts as a relay, and use the constant nullptr as a special value for this, if you want to be able to pass other values:
class B
{
public:
A a;
B()
{
//Calling 'dowithT' with 'this'
innerdo();
}
private:
void innerdo(B *p = nullptr) {
if (p == nullptr) p = this;
a.dowithT(p);
}
};
If you only need to pass this it is even simpler
void innerdo() {
a.dowithT(this);
}
After trying out various things you mentioned, I'd like to give my answer/solution to the problem myself to clarify some details:
#include <iostream>
using namespace std;
#include <functional>
template <typename CallerType>
class AFunctionConstructor{
private:
virtual void abstr()
{}
public:
typedef void(CallerType::*CallerTypeFunc)();
function<void()>* constructFunction(CallerTypeFunc func)
{
CallerType* newMe = dynamic_cast<CallerType*> (this);
return new function<void()>(std::bind(func,newMe));
}
};
class A : public function<void()>
{
protected:
public:
A();
A(function<void()>* func) : function<void()>(*func)
{}
};
// now create ressource classes
// they provide functions to be called via an object of class A
class B : public AFunctionConstructor<B>
{
void foo()
{
cout << "Foo";
}
public:
A a;
B() : a(constructFunction(&B::foo)) {}
};
class C : public AFunctionConstructor < C >
{
void bar()
{
cout << "Bar";
}
public:
A a;
C() : a(constructFunction(&C::bar)) {}
};
int main()
{
B b;
C c;
b.a();
c.a();
cout << endl;
A* array[5];
array[0] = &b.a; //different functions with their ressources
array[1] = &c.a;
array[2] = &b.a;
array[3] = &c.a;
array[4] = &c.a;
for (int i = 0; i < 5; i++) //this usability i wanted to provide
{
(*(array[i]))();
}
getchar();
return 0;
}
Output :
FooBar
FooBarFooBarBar
This is as far as i can press it down concerning examples. But i guess this is unsafe code. I stumbled across possible other and simpler ways to achieve this (other uses of std::function and lambdas(which i might have tried to reinvent here partially it seems)).
At first I had tried to pass "this" to the bind function in function<void()>*AFunctionConstructor::constructFunction(CallerTypeFunc func)
,though, which i now get through the dynamic upcast.
Additionally the functionality of AFunctionConstructor was first supposed to be implemented in a Constructor of A.
I am working on translating some Java code into C++. When I try to write code like:
.h:
class A {
private:
class B;
std::set<B> b_set;
};
.cpp:
class A::B {
};
I got an incomplete type error. I understand that that is because the nested class is incomplete before using it in b_set. But what's the best way to fix it?
You can describe your entire B class in the .h file.
Here's a working example.
#include<set>
class A {
private:
class B{
B():foo(1){}
int foo;
};
std::set<B> b_set;
};
However, if you want to separate your definition and instantiation, you can do this:
A.h
#include<set>
class A {
private:
class B{
public:
B();
private:
int someMethod();
int foo;
};
std::set<B> b_set;
};
A.cpp
#include "A.h"
A::B::B():foo(1){}
int A::B::someMethod(){
return 42;
}
Generally speaking, nested classes can be a serious PITA because of all the hoops you have to jump through to access anything from them.
Another good reference on nested classes: Nested class definition in source file
Well, I'm late, I know, still I want to point out another possibility, if you want to completely hide away the internals of class B:
class A
{
private:
class B;
std::set<B*> b_set;
};
Notice using pointers in the set. However, there is yet left an important difference: as only pointers are inserted, you can still insert pointers to different instances having the same content. To solve this, you need a custom comparator:
class A
{
private:
class B;
struct Less
{
bool operator() (B const* x, B const* y) const
{
return *x < *y;
}
};
std::set<B*, Less> b_set;
};
Be aware (this was not mentioned in the previous answer, but is required there, too!) that there must be defined a comparator for B (B or reference to, not pointer!):
A.h
#include <set>
class A
{
private:
class B;
struct Less
{
bool operator() (B const* x, B const* y) const;
};
std::set<B*, Less> b_set;
};
A.cpp
class A::B
{
friend bool Less::operator() (B const* x, B const* y) const;
bool operator<(B const& other) const
{
return foo < other.foo;
}
int foo;
};
bool A::Less::operator() (B const* x, B const* y) const
{
return *x < *y;
}
This allows to hide away B completely from the header, if you want or need to for any reason. However, you cannot insert objects from the stack directly any more, as they are not copied and you have pointers to the stack that quickly get invalid. Special care has to be taken for deleting the objects when they are not needed any more, or you get memory leaks. Remember that there is no garbage collection as you know from Java. If using C++11, you can alleviate the problem using ::std::unique_ptr, before, ::std::auto_ptr:
A.h
#include <set>
#include <memory>
class A
{
private:
class B;
struct Less
{
bool operator() (B const* x, B const* y) const;
};
std::set<std::unique_ptr<B>, Less> b_set;
};
I have multiple classes that need to share a single instance of another class. Publicly it should be unknown that this class exists. Is it appropriate to do something like the following? (Was tested as written)
#include <iostream>
class hideme
{
private:
int a;
public:
void set(int b) { a = b; }
void add(int b) { a += b; }
int get() { return a; }
hideme() : a(0) { }
};
class HiddenWrapper
{
protected:
static hideme A;
};
hideme HiddenWrapper::A;
class addOne : public HiddenWrapper
{
public:
void add() { A.add(1); }
int get() { return A.get(); }
};
class addTwo : public HiddenWrapper
{
public:
void add() { A.add(2); }
int get() { return A.get(); }
};
int main()
{
addOne a;
addTwo b;
std::cout << "Initialized: " << a.get() << std::endl;
a.add();
std::cout << "Added one: " << a.get() << std::endl;
b.add();
std::cout << "Added two: " << b.get() << std::endl;
return 0;
}
For what it's worth, hideme is part of a library I'm attempting to design a facade around, and the other classes have members from the library that interact with the static hideme.
Additionally, if the header file written for HiddenWrapper has no corresponding source file, is that the best place to define its static member? With an include guard.
Is there any other method to solve this problem? As far as I could imagine (not terribly far) I could only solve it otherwise with friendship, which I am wary of.
You can prevent access to a class by not making it accessible outside the translation unit that uses it.
// public_header.h
class A {
void bar();
};
class B {
void foo();
}
// private_implementation.cpp
#include "public_header.h"
namespace {
class hidden { void baz() {} };
hidden h;
}
void A::bar() {
h.baz();
}
void B::foo() {
h.baz();
}
This class will be usable only by A::bar and B::foo. The type hidden and the variable h still technically have external linkage, but no other translation unit can say their names.
Sometimes it is a better idea to inject shared ressources (by reference or pointer) through the constructor (also known as composition instead of inheritance). This way gives you the ability to share or not (e.g. to have a thread-safe variant of your code which is not). See http://de.wikipedia.org/wiki/Inversion_of_Control principle for more info.
This implements a singleton around some other class and hides it from
users:
class hideme {};
// fwd declarations
class x;
// library internal
class S
{
S() = delete;
S(S const&) = delete;
void operator=(S const&) = delete;
private:
static hideme& getInstance()
{
static hideme instance;
return instance;
}
friend x;
};
// library classes
class x {
hideme& s;
public:
x() : s(S::getInstance()) {}
};
int main()
{
x x;
return 0;
}
This does not handle cases where you actually want the hideme
instance to be destroyed when no other object is using it anymore. For
that you need to get a little bit more inventive using reference
counting.
I also should say that I think this is a bad idea. Singletons almost
always are.
Generally, the best approach, if you have a variable in the main part, and want to share it with all classes.
For example, if class X makes a change on this var, the change happened to the var in the main as well: you can use EXTEND
************************ The main *********************
#include <iostream>
using namespace std;
#include "Game.hpp"
//0: not specified yet; 1:singlemode; 2:multiplayerMode
int playingMode = 0;
int main()
{
Game game;
game.Run();
std::cout<< playingMode << std::endl;
return 0;
}
*********************** Class X *****************
#include <iostream>
using namespace std;
extern int playingMode;
....
....
if(m_isSinglePressed)
{
playingMode = 1;
...
}
else if(m_isMultiPressed)
{
playingMode = 2;
...
}