Object Oriented Graph Hierarchy with Depth First Search
General
Depth first search generally applies to trees (because it has a depth, no cycles). You have implemented a general purpose graph (which can contain cycles and thus is not a tree (and does not have a depth).
Code Review
Pragmas are compiler specific. They are fine if you use them taking this into context.
#pragma once

This pragma is basically useless as it is non portable. Use the appropriate include guards unless you want to be locked into your current compiler only.
Not sure why you need to make isVisitied a member.
class BiGraph :public Graph
{
    std::vector&lt;bool&gt; isVisited;

The only reason you seem to need it was because areConnected() returns it by reference.
const std::vector&lt;bool&gt;&amp;  areConnected(int sourcevertex)

I assume you did this to save the cost of copying the vector out. This is a false optimization. C++ is highly optimized and it is unlikely that a return by value would be copied out. The compiler has aggrissive RVO/NRVO optimization that would build the result at the destionation. In C++11 move semantics are introduced and compliment the RVO/NRVO optimization and in the few cases were they can not be built in place move semantics kick in and the content is moved optimally out of the method.
So declare this function
const std::vector&lt;bool&gt;  areConnected(int sourcevertex) const;

The specialization std::vector&lt;bool&gt; is broadly considered a mistake. It is optimized for size (unlike nearly everything else in C++ which is optimized for speed).
Because it optimized for size it has several drawbacks and does not act like a normal std::vector&lt;&gt; (which is why it is normally avoided). Now if you think you need to optimize for size then fair enough but normally people prefer to use std::vector&lt;char&gt;
Simpler Issues
Sure.
void ZeroBoolArray(std::vector&lt;bool&gt;&amp; arr)

But if you fix the code as I suggeste above you don't need this function.
There is a simpler way to write this:
for (auto &amp;x : arr)
{
    x = false;
}

// Easier to write as:
x = std::vector&lt;bool&gt;(x.size());   // Might be slightly more expensive.

Please one variable per line. This includes initializee list.
// This is unreadable
BiGraph::BiGraph(int maxvertexcount_, std::string name_):graph(maxvertexcount_), maxVertexCount(maxvertexcount_), name(name_), isVisited(maxVertexCount)
{

}

// Rewrite as:
BiGraph::BiGraph(int maxvertexcount_, std::string name_)
    : graph(maxvertexcount_)
    , maxVertexCount(maxvertexcount_)
    , name(name_)
    , isVisited(maxVertexCount)
{}
// PS I hate the trailing `_` there is no need to have it.
// If you re-write as:
BiGraph::BiGraph(int maxvertexcount, std::string name)
    : graph(maxvertexcount)
    , maxVertexCount(maxvertexcount)
    , name(name)
    , isVisited(maxVertexCount)
{}
// this works just as well and is unambiguous.

Why only check fVertex?
void BiGraph::addAdjacentImpl(int fVertex, int sVertex)
{
    if (fVertex &gt; maxVertexCount)
    {
        throw std::out_of_range(name + &quot;: trying to add vertex which doesn't exist&quot;);
    }

You should probably also check sVertex. But unless you explicitly want that error message you don't need the test; just use at() method.
void BiGraph::addAdjacentImpl(int fVertex, int sVertex)
{
    graph.at(fVertex).push_back(sVertex);
    graph.at(sVertex).push_back(fVertex);
}

Also you don't check if the vertex has already been added.
Sure this works fine. But it would be better to use the Visitor Pattern.
void BiGraph::traverse(int sourceVertex)

We covered this function above:
const std::vector&lt;bool&gt;&amp; BiGraph::areConnectedImpl(int sourceVertex)

// I would write as:
const std::vector&lt;char&gt; BiGraph::areConnectedImpl(int sourceVertex) const
{
    std::vector&lt;char&gt;  isVisited.
    traverse(sourceVertex, isVisited);
    return isVisited;
}

If your destructor does nothing then don't declare it. The compiler generated version will work perfectly well.
BiGraph::~BiGraph()

Sure: This printImpl() seems easy enough. But it could be improved.
void BiGraph::printImpl() const

Rather than assume you will print to std::cout take a parameter for the output stream to be used. It can default to std::cout but this gives you the flexability to use other streams (like files/string streams etc).
Also in C++ it is standard to define an output operator to print an object.
Prefer &quot;\n&quot; over std::endl. The std::endl will also flush the stream which will usually make the code sub optimal. The stream is already flushed automatically if needed and if not needed will flush at optimal points so there is no need to manually force a flush.
Prefer the range based for loop if you don't need the index (currently your j loop is wrong (you should print the value at each index).
void BiGraph::printImpl(std::ostream&amp; str = std::cout) const
{
    for (size_t i = 0; i &lt; graph.size(); i++)
    {
        str &lt;&lt; i &lt;&lt; &quot;: &quot;;
        for (auto j: graph[i])
        {
            str &lt;&lt; j &lt;&lt; ' ';
        }
        str &lt;&lt; &quot;\n&quot;;
    }
}
std::ostream&amp; operator&lt;&lt;(std::ostream^ str, Graph const&amp; g)
{
    g.print(str);
    return str;
}