Skip to content

Instantly share code, notes, and snippets.

@sansumbrella
Last active December 19, 2021 19:20
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sansumbrella/6602912 to your computer and use it in GitHub Desktop.
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).
#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