Last active
December 19, 2021 19:20
-
-
Save sansumbrella/6602912 to your computer and use it in GitHub Desktop.
Sample showing use of forward declarations to handle circular dependencies.
Also note the use of weak_ptr to break circular references (which would leak).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <memory> | |
using namespace std; | |
/** | |
Demonstration of circular dependencies broken with forward declarations. | |
Compile like so: | |
clang++ -std=c++11 -stdlib=libc++ circular.cpp -o build/circular && build/circular | |
*/ | |
// make forward declarations of classes that will exist | |
class Thinker; | |
class Doer; | |
// make full declarations of classes | |
class Thinker | |
{ | |
public: | |
Thinker( const string &name ): | |
mName( name ) | |
{} | |
void setDoer( weak_ptr<Doer> doer ){ mDoer = doer; } | |
string think(); | |
string getName() const { return mName; } | |
private: | |
weak_ptr<Doer> mDoer; | |
string mName; | |
}; | |
// thinker didn't need to be forward-declared here since it's all | |
// written inline, but it would if this were in a separate header | |
class Doer | |
{ | |
public: | |
Doer( const string &name, weak_ptr<Thinker> thinker ): | |
mName( name ), | |
mThinker( thinker ) | |
{} | |
string act(); | |
string getName() const { return mName; } | |
private: | |
string mName; | |
weak_ptr<Thinker> mThinker; | |
}; | |
// The forward declared things have now been fully declared | |
// let's define the functions that use them | |
// (would be in .cpp files) | |
string Doer::act() | |
{ | |
auto thinker = mThinker.lock(); // get a strong reference | |
if( thinker ) | |
{ | |
return "Acting on thought considered by " + thinker->getName() + "."; | |
} | |
return "No to do things for."; | |
} | |
string Thinker::think() | |
{ | |
auto doer = mDoer.lock(); | |
if( doer ) | |
{ | |
return "Thinking thoughts for " + doer->getName() + "."; | |
} | |
return "No one to think for."; | |
} | |
int main( int argc, const char *argv[] ) | |
{ | |
auto thinker = make_shared<Thinker>( "Metis" ); | |
auto doer = make_shared<Doer>( "Thor", thinker ); | |
cout << thinker->think() << endl; // no one to think for | |
thinker->setDoer( doer ); // assign complement | |
cout << thinker->think() << endl; | |
cout << doer->act() << endl; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment